Просмотр исходного кода

Merge pull request #1423 from MissAllSunday/minor-stuff

Minor stuff reported posts
Michael Eshom 10 лет назад
Родитель
Сommit
4b3a023aa7

+ 27 - 588
Sources/ModerationCenter.php

@@ -125,11 +125,11 @@ function ModerationMain($dont_call = false)
 				'reports' => array(
 					'label' => $txt['mc_reported_posts'],
 					'enabled' => $context['can_moderate_boards'],
-					'file' => 'ModerationCenter.php',
+					'file' => 'ReportedPosts.php',
 					'function' => 'ReportedPosts',
 					'icon' => 'reports.png',
 					'subsections' => array(
-						'open' => array($txt['mc_reportedp_active']),
+						'show' => array($txt['mc_reportedp_active']),
 						'closed' => array($txt['mc_reportedp_closed']),
 					),
 				),
@@ -337,10 +337,15 @@ function ModBlockNotes()
 {
 	global $context, $smcFunc, $scripturl, $txt, $user_info;
 
+	// Set a nice and informative message.
+	$context['report_post_action'] = !empty($_SESSION['rc_confirmation']) ? $_SESSION['rc_confirmation'] : array();
+	unset($_SESSION['rc_confirmation']);
+
 	// Are we saving a note?
 	if (isset($_GET['modnote']) && isset($_POST['makenote']) && isset($_POST['new_note']))
 	{
 		checkSession();
+		validateToken('mod-modnote-add');
 
 		$_POST['new_note'] = $smcFunc['htmlspecialchars'](trim($_POST['new_note']));
 		// Make sure they actually entered something.
@@ -364,6 +369,9 @@ function ModBlockNotes()
 			cache_put_data('moderator_notes_total', null, 240);
 		}
 
+		// Everything went better than expected!
+		$_SESSION['rc_confirmation'] = 'message_saved';
+
 		// Redirect otherwise people can resubmit.
 		redirectexit('action=moderate');
 	}
@@ -372,15 +380,15 @@ function ModBlockNotes()
 	if (isset($_GET['notes']) && isset($_GET['delete']) && is_numeric($_GET['delete']))
 	{
 		checkSession('get');
+		validateToken('mod-modnote-del', 'get');
 
 		// Lets delete it.
 		$smcFunc['db_query']('', '
 			DELETE FROM {db_prefix}log_comments
 			WHERE id_comment = {int:note}
-				AND comment_type = {string:type}',
+				AND comment_type = {literal:modnote}',
 			array(
 				'note' => $_GET['delete'],
-				'type' => 'modnote',
 			)
 		);
 
@@ -388,6 +396,9 @@ function ModBlockNotes()
 		cache_put_data('moderator_notes', null, 240);
 		cache_put_data('moderator_notes_total', null, 240);
 
+		// Tell them the message was deleted.
+		$_SESSION['rc_confirmation'] = 'message_deleted';
+
 		redirectexit('action=moderate');
 	}
 
@@ -398,9 +409,8 @@ function ModBlockNotes()
 			SELECT COUNT(*)
 			FROM {db_prefix}log_comments AS lc
 				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
-			WHERE lc.comment_type = {string:modnote}',
+			WHERE lc.comment_type = {literal:modnote}',
 			array(
-				'modnote' => 'modnote',
 			)
 		);
 		list ($moderator_notes_total) = $smcFunc['db_fetch_row']($request);
@@ -418,11 +428,10 @@ function ModBlockNotes()
 				lc.log_time, lc.body, lc.id_comment AS id_note
 			FROM {db_prefix}log_comments AS lc
 				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
-			WHERE lc.comment_type = {string:modnote}
+			WHERE lc.comment_type = {literal:modnote}
 			ORDER BY id_comment DESC
 			LIMIT {int:offset}, 10',
 			array(
-				'modnote' => 'modnote',
 				'offset' => $offset,
 			)
 		);
@@ -453,6 +462,16 @@ function ModBlockNotes()
 		);
 	}
 
+	// Add a confirm on deleting a modnote
+	addInlineJavascript('
+	$(\'.delete_modnote\').on(\'click\', function(){
+			return confirm('. JavaScriptEscape($txt['mc_reportedp_delete_confirm']) .');
+	});', true);
+
+	// Couple tokens for add/delete modnotes
+	createToken('mod-modnote-add');
+	createToken('mod-modnote-del', 'get');
+
 	return 'notes';
 }
 
@@ -635,275 +654,6 @@ function ModBlockReportedMembers()
 	return 'reported_users_block';
 }
 
-/**
- * Browse all the reported posts...
- * @todo this needs to be given its own file?
- */
-function ReportedPosts()
-{
-	global $txt, $context, $scripturl, $user_info, $smcFunc;
-
-	loadTemplate('ModerationCenter');
-
-	// Set an empty var for the server response.
-	$context['report_post_action'] = '';
-
-	// Put the open and closed options into tabs, because we can...
-	$context[$context['moderation_menu_name']]['tab_data'] = array(
-		'title' => $txt['mc_reported_posts'],
-		'help' => '',
-		'description' => $txt['mc_reported_posts_desc'],
-	);
-
-	// This comes under the umbrella of moderating posts.
-	if ($user_info['mod_cache']['bq'] == '0=1')
-		isAllowedTo('moderate_forum');
-
-	// Are they wanting to view a particular report?
-	if (!empty($_REQUEST['report']))
-		return ModReport();
-
-	// Set up the comforting bits...
-	$context['page_title'] = $txt['mc_reported_posts'];
-	$context['sub_template'] = 'reported_posts';
-
-	// Are we viewing open or closed reports?
-	$context['view_closed'] = isset($_GET['sa']) && $_GET['sa'] == 'closed' ? 1 : 0;
-
-	// Are we doing any work?
-	if ((isset($_GET['ignore']) || isset($_GET['close'])) && isset($_GET['rid']))
-	{
-		checkSession('get');
-		$_GET['rid'] = (int) $_GET['rid'];
-
-		// Update the report...
-		$smcFunc['db_query']('', '
-			UPDATE {db_prefix}log_reported
-			SET ' . (isset($_GET['ignore']) ? 'ignore_all = {int:ignore_all}' : 'closed = {int:closed}') . '
-			WHERE id_report = {int:id_report}
-				AND ' . $user_info['mod_cache']['bq'],
-			array(
-				'ignore_all' => isset($_GET['ignore']) ? (int) $_GET['ignore'] : 0,
-				'closed' => isset($_GET['close']) ? (int) $_GET['close'] : 0,
-				'id_report' => $_GET['rid'],
-			)
-		);
-
-		// Get the board, topic and message for this report
-		$request = $smcFunc['db_query']('', '
-			SELECT id_board, id_topic, id_msg
-			FROM {db_prefix}log_reported
-			WHERE id_report = {int:id_report}',
-			array(
-				'id_report' => $_GET['rid'],
-			)
-		);
-
-		// Set up the data for the log...
-		$extra = array('report' => $_GET['rid']);
-		list ($extra['board'], $extra['topic'], $extra['message']) = $smcFunc['db_fetch_row']($request);
-		$smcFunc['db_free_result']($request);
-
-		// Tell the user about it.
-		$context['report_post_action'] = isset($_GET['ignore']) ? (!empty($_GET['ignore']) ? 'ignore' : 'unignore') : (!empty($_GET['close']) ? 'close' : 'open');
-
-		// Log this action
-		logAction($context['report_post_action'] . '_report', $extra);
-
-		// Time to update.
-		updateSettings(array('last_mod_report_action' => time()));
-		recountOpenReports();
-	}
-	elseif (isset($_POST['close']) && isset($_POST['close_selected']))
-	{
-		checkSession();
-
-		// All the ones to update...
-		$toClose = array();
-		foreach ($_POST['close'] as $rid)
-			$toClose[] = (int) $rid;
-
-		if (!empty($toClose))
-		{
-			// Get the data for each of these reports
-			$request = $smcFunc['db_query']('', '
-				SELECT id_report, id_board, id_topic, id_msg
-				FROM {db_prefix}log_reported
-				WHERE id_report IN ({array_int:report_list})
-					AND ' . $user_info['mod_cache']['bq'],
-				array(
-					'report_list' => $toClose,
-				)
-			);
-
-			while ($reports = $smcFunc['db_fetch_assoc']($request))
-			{
-				$report_data = array(
-					'report' => $row['id_report'],
-					'board' => $row['id_board'],
-					'topic' => $row['id_topic'],
-					'message' => $row['id_msg'],
-				);
-
-				// Log that this report was closed
-				logAction('close_report', $report_data);
-			}
-
-			$smcFunc['db_free_result']($request);
-
-			$smcFunc['db_query']('', '
-				UPDATE {db_prefix}log_reported
-				SET closed = {int:is_closed}
-				WHERE id_report IN ({array_int:report_list})
-					AND ' . $user_info['mod_cache']['bq'],
-				array(
-					'report_list' => $toClose,
-					'is_closed' => 1,
-				)
-			);
-
-			// Time to update.
-			updateSettings(array('last_mod_report_action' => time()));
-			recountOpenReports();
-		}
-
-		// Go on and tell the result.
-		$context['report_post_action'] = 'close_all';
-	}
-
-	// How many entries are we viewing?
-	$request = $smcFunc['db_query']('', '
-		SELECT COUNT(*)
-		FROM {db_prefix}log_reported AS lr
-		WHERE lr.closed = {int:view_closed}
-			AND ' . ($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']) . '
-			AND lr.id_board != {int:not_a_reported_post}',
-		array(
-			'view_closed' => $context['view_closed'],
-			'not_a_reported_post' => 0,
-		)
-	);
-	list ($context['total_reports']) = $smcFunc['db_fetch_row']($request);
-	$smcFunc['db_free_result']($request);
-
-	// So, that means we can page index, yes?
-	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=reports' . ($context['view_closed'] ? ';sa=closed' : ''), $_GET['start'], $context['total_reports'], 10);
-	$context['start'] = $_GET['start'];
-
-	// By George, that means we in a position to get the reports, golly good.
-	$request = $smcFunc['db_query']('', '
-		SELECT lr.id_report, lr.id_msg, lr.id_topic, lr.id_board, lr.id_member, lr.subject, lr.body,
-			lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
-			IFNULL(mem.real_name, lr.membername) AS author_name, IFNULL(mem.id_member, 0) AS id_author
-		FROM {db_prefix}log_reported AS lr
-			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
-		WHERE lr.closed = {int:view_closed}
-			AND ' . ($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']) . '
-			AND lr.id_board != {int:not_a_reported_post}
-		ORDER BY lr.time_updated DESC
-		LIMIT ' . $context['start'] . ', 10',
-		array(
-			'view_closed' => $context['view_closed'],
-			'not_a_reported_post' => 0,
-		)
-	);
-	$context['reports'] = array();
-	$report_ids = array();
-	$report_boards_ids = array();
-	for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i++)
-	{
-		$report_ids[] = $row['id_report'];
-		$report_boards_ids[] = $row['id_board'];
-		$context['reports'][$row['id_report']] = array(
-			'id' => $row['id_report'],
-			'alternate' => $i % 2,
-			'topic' => array(
-				'id' => $row['id_topic'],
-				'id_msg' => $row['id_msg'],
-				'id_board' => $row['id_board'],
-				'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
-			),
-			'report_href' => $scripturl . '?action=moderate;area=reports;report=' . $row['id_report'],
-			'author' => array(
-				'id' => $row['id_author'],
-				'name' => $row['author_name'],
-				'link' => $row['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_author'] . '">' . $row['author_name'] . '</a>' : $row['author_name'],
-				'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
-			),
-			'comments' => array(),
-			'time_started' => timeformat($row['time_started']),
-			'last_updated' => timeformat($row['time_updated']),
-			'subject' => $row['subject'],
-			'body' => parse_bbc($row['body']),
-			'num_reports' => $row['num_reports'],
-			'closed' => $row['closed'],
-			'ignore' => $row['ignore_all']
-		);
-	}
-	$smcFunc['db_free_result']($request);
-
-	// Get the names of boards those topics are in. Slightly faster this way.
-	if (!empty($report_boards_ids))
-	{
-		$report_boards_ids = array_unique($report_boards_ids);
-		$board_names = array();
-		$request = $smcFunc['db_query']('', '
-			SELECT id_board, name
-			FROM {db_prefix}boards
-			WHERE id_board IN ({array_int:boards})',
-			array(
-				'boards' => $report_boards_ids,
-			)
-		);
-
-		while ($row = $smcFunc['db_fetch_assoc']($request))
-			$board_names[$row['id_board']] = $row['name'];
-		$smcFunc['db_free_result']($request);
-
-		foreach ($context['reports'] as $id_report => $report)
-			if (!empty($board_names[$report['topic']['id_board']]))
-				$context['reports'][$id_report]['topic']['board_name'] = $board_names[$report['topic']['id_board']];
-	}
-
-	// Now get all the people who reported it.
-	if (!empty($report_ids))
-	{
-		$request = $smcFunc['db_query']('', '
-			SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment,
-				IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lrc.membername) AS reporter
-			FROM {db_prefix}log_reported_comments AS lrc
-				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
-			WHERE lrc.id_report IN ({array_int:report_list})',
-			array(
-				'report_list' => $report_ids,
-			)
-		);
-		while ($row = $smcFunc['db_fetch_assoc']($request))
-		{
-			$context['reports'][$row['id_report']]['comments'][] = array(
-				'id' => $row['id_comment'],
-				'message' => $row['comment'],
-				'time' => timeformat($row['time_sent']),
-				'member' => array(
-					'id' => $row['id_member'],
-					'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
-					'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
-					'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
-				),
-			);
-		}
-		$smcFunc['db_free_result']($request);
-	}
-
-	// Get the boards where the current user can remove any message.
-	$context['report_remove_any_boards'] = $user_info['is_admin'] ? $report_boards_ids : array_intersect($report_boards_ids, boardsAllowedTo('remove_any'));
-	$context['report_manage_bans'] = allowedTo('manage_bans');
-
-	// Do we deleted a message?
-	if (isset($_REQUEST['done']))
-		$context['report_post_action'] = 'message_deleted';
-}
-
 /**
  * Browse all the reported users...
  */
@@ -1156,38 +906,6 @@ function ModerateGroups()
 	$subactions[$context['sub_action']]();
 }
 
-/**
- * How many open reports do we have?
- */
-function recountOpenReports()
-{
-	global $user_info, $context, $smcFunc;
-
-	$request = $smcFunc['db_query']('', '
-		SELECT COUNT(*)
-		FROM {db_prefix}log_reported
-		WHERE ' . $user_info['mod_cache']['bq'] . '
-			AND closed = {int:not_closed}
-			AND ignore_all = {int:not_ignored}
-			AND id_board != {int:not_a_reported_post}',
-		array(
-			'not_closed' => 0,
-			'not_ignored' => 0,
-			'not_a_reported_post' => 0,
-		)
-	);
-	list ($open_reports) = $smcFunc['db_fetch_row']($request);
-	$smcFunc['db_free_result']($request);
-
-	$_SESSION['rc'] = array(
-		'id' => $user_info['id'],
-		'time' => time(),
-		'reports' => $open_reports,
-	);
-
-	$context['open_mod_reports'] = $open_reports;
-}
-
 /**
  * How many open reports do we have?
  */
@@ -1219,285 +937,6 @@ function recountOpenMemberReports()
 	$context['open_member_reports'] = $open_reports;
 }
 
-/**
- * Get details about the moderation report... specified in
- * $_REQUEST['report'].
- */
-function ModReport()
-{
-	global $user_info, $context, $sourcedir, $scripturl, $txt, $smcFunc;
-
-	// Have to at least give us something
-	if (empty($_REQUEST['report']))
-		fatal_lang_error('mc_no_modreport_specified');
-
-	// Integers only please
-	$_REQUEST['report'] = (int) $_REQUEST['report'];
-
-	// Get the report details, need this so we can limit access to a particular board
-	$request = $smcFunc['db_query']('', '
-		SELECT lr.id_report, lr.id_msg, lr.id_topic, lr.id_board, lr.id_member, lr.subject, lr.body,
-			lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
-			IFNULL(mem.real_name, lr.membername) AS author_name, IFNULL(mem.id_member, 0) AS id_author
-		FROM {db_prefix}log_reported AS lr
-			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
-		WHERE lr.id_report = {int:id_report}
-			AND ' . ($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']) . '
-			AND lr.id_board != {int:not_a_reported_post}
-		LIMIT 1',
-		array(
-			'id_report' => $_REQUEST['report'],
-			'not_a_reported_post' => 0,
-		)
-	);
-
-	// So did we find anything?
-	if (!$smcFunc['db_num_rows']($request))
-		fatal_lang_error('mc_no_modreport_found');
-
-	// Woohoo we found a report and they can see it!  Bad news is we have more work to do
-	$row = $smcFunc['db_fetch_assoc']($request);
-	$smcFunc['db_free_result']($request);
-
-	// If they are adding a comment then... add a comment.
-	if (isset($_POST['add_comment']) && !empty($_POST['mod_comment']))
-	{
-		checkSession();
-
-		$newComment = trim($smcFunc['htmlspecialchars']($_POST['mod_comment']));
-
-		// In it goes.
-		if (!empty($newComment))
-		{
-			$smcFunc['db_insert']('',
-				'{db_prefix}log_comments',
-				array(
-					'id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'recipient_name' => 'string',
-					'id_notice' => 'int', 'body' => 'string', 'log_time' => 'int',
-				),
-				array(
-					$user_info['id'], $user_info['name'], 'reportc', '',
-					$_REQUEST['report'], $newComment, time(),
-				),
-				array('id_comment')
-			);
-			$last_comment = $smcFunc['db_insert_id']('{db_prefix}log_comments', 'id_comment');
-
-			// And get ready to notify people.
-			$smcFunc['db_insert']('insert',
-				'{db_prefix}background_tasks',
-				array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'),
-				array('$sourcedir/tasks/MsgReportReply-Notify.php', 'MsgReportReply_Notify_Background', serialize(array(
-					'report_id' => $_REQUEST['report'],
-					'comment_id' => $last_comment,
-					'msg_id' => $row['id_msg'],
-					'topic_id' => $row['id_topic'],
-					'board_id' => $row['id_board'],
-					'sender_id' => $user_info['id'],
-					'sender_name' => $user_info['name'],
-					'time' => time(),
-				)), 0),
-				array('id_task')
-			);
-
-			// Redirect to prevent double submittion.
-			redirectexit($scripturl . '?action=moderate;area=reports;report=' . $_REQUEST['report']);
-		}
-	}
-
-	$context['report'] = array(
-		'id' => $row['id_report'],
-		'topic_id' => $row['id_topic'],
-		'board_id' => $row['id_board'],
-		'message_id' => $row['id_msg'],
-		'message_href' => $scripturl . '?msg=' . $row['id_msg'],
-		'message_link' => '<a href="' . $scripturl . '?msg=' . $row['id_msg'] . '">' . $row['subject'] . '</a>',
-		'report_href' => $scripturl . '?action=moderate;area=reports;report=' . $row['id_report'],
-		'author' => array(
-			'id' => $row['id_author'],
-			'name' => $row['author_name'],
-			'link' => $row['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_author'] . '">' . $row['author_name'] . '</a>' : $row['author_name'],
-			'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
-		),
-		'comments' => array(),
-		'mod_comments' => array(),
-		'time_started' => timeformat($row['time_started']),
-		'last_updated' => timeformat($row['time_updated']),
-		'subject' => $row['subject'],
-		'body' => parse_bbc($row['body']),
-		'num_reports' => $row['num_reports'],
-		'closed' => $row['closed'],
-		'ignore' => $row['ignore_all']
-	);
-
-	// So what bad things do the reporters have to say about it?
-	$request = $smcFunc['db_query']('', '
-		SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment, lrc.member_ip,
-			IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lrc.membername) AS reporter
-		FROM {db_prefix}log_reported_comments AS lrc
-			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
-		WHERE lrc.id_report = {int:id_report}',
-		array(
-			'id_report' => $context['report']['id'],
-		)
-	);
-	while ($row = $smcFunc['db_fetch_assoc']($request))
-	{
-		$context['report']['comments'][] = array(
-			'id' => $row['id_comment'],
-			'message' => strtr($row['comment'], array("\n" => '<br>')),
-			'time' => timeformat($row['time_sent']),
-			'member' => array(
-				'id' => $row['id_member'],
-				'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
-				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
-				'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
-				'ip' => !empty($row['member_ip']) && allowedTo('moderate_forum') ? '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>' : '',
-			),
-		);
-	}
-	$smcFunc['db_free_result']($request);
-
-	// Hang about old chap, any comments from moderators on this one?
-	$request = $smcFunc['db_query']('', '
-		SELECT lc.id_comment, lc.id_notice, lc.log_time, lc.body,
-			IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lc.member_name) AS moderator
-		FROM {db_prefix}log_comments AS lc
-			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
-		WHERE lc.id_notice = {int:id_report}
-			AND lc.comment_type = {literal:reportc}',
-		array(
-			'id_report' => $context['report']['id'],
-		)
-	);
-	while ($row = $smcFunc['db_fetch_assoc']($request))
-	{
-		$context['report']['mod_comments'][] = array(
-			'id' => $row['id_comment'],
-			'message' => parse_bbc($row['body']),
-			'time' => timeformat($row['log_time']),
-			'member' => array(
-				'id' => $row['id_member'],
-				'name' => $row['moderator'],
-				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['moderator'] . '</a>' : $row['moderator'],
-				'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
-			),
-		);
-	}
-	$smcFunc['db_free_result']($request);
-
-	// What have the other moderators done to this message?
-	require_once($sourcedir . '/Modlog.php');
-	require_once($sourcedir . '/Subs-List.php');
-	loadLanguage('Modlog');
-
-	// This is all the information from the moderation log.
-	$listOptions = array(
-		'id' => 'moderation_actions_list',
-		'title' => $txt['mc_modreport_modactions'],
-		'items_per_page' => 15,
-		'no_items_label' => $txt['modlog_no_entries_found'],
-		'base_href' => $scripturl . '?action=moderate;area=reports;report=' . $context['report']['id'],
-		'default_sort_col' => 'time',
-		'get_items' => array(
-			'function' => 'list_getModLogEntries',
-			'params' => array(
-				'lm.id_topic = {int:id_topic}',
-				array('id_topic' => $context['report']['topic_id']),
-				1,
-			),
-		),
-		'get_count' => array(
-			'function' => 'list_getModLogEntryCount',
-			'params' => array(
-				'lm.id_topic = {int:id_topic}',
-				array('id_topic' => $context['report']['topic_id']),
-				1,
-			),
-		),
-		// This assumes we are viewing by user.
-		'columns' => array(
-			'action' => array(
-				'header' => array(
-					'value' => $txt['modlog_action'],
-				),
-				'data' => array(
-					'db' => 'action_text',
-					'class' => 'smalltext',
-				),
-				'sort' => array(
-					'default' => 'lm.action',
-					'reverse' => 'lm.action DESC',
-				),
-			),
-			'time' => array(
-				'header' => array(
-					'value' => $txt['modlog_date'],
-				),
-				'data' => array(
-					'db' => 'time',
-					'class' => 'smalltext',
-				),
-				'sort' => array(
-					'default' => 'lm.log_time',
-					'reverse' => 'lm.log_time DESC',
-				),
-			),
-			'moderator' => array(
-				'header' => array(
-					'value' => $txt['modlog_member'],
-				),
-				'data' => array(
-					'db' => 'moderator_link',
-					'class' => 'smalltext',
-				),
-				'sort' => array(
-					'default' => 'mem.real_name',
-					'reverse' => 'mem.real_name DESC',
-				),
-			),
-			'position' => array(
-				'header' => array(
-					'value' => $txt['modlog_position'],
-				),
-				'data' => array(
-					'db' => 'position',
-					'class' => 'smalltext',
-				),
-				'sort' => array(
-					'default' => 'mg.group_name',
-					'reverse' => 'mg.group_name DESC',
-				),
-			),
-			'ip' => array(
-				'header' => array(
-					'value' => $txt['modlog_ip'],
-				),
-				'data' => array(
-					'db' => 'ip',
-					'class' => 'smalltext',
-				),
-				'sort' => array(
-					'default' => 'lm.ip',
-					'reverse' => 'lm.ip DESC',
-				),
-			),
-		),
-	);
-
-	// Create the watched user list.
-	createList($listOptions);
-
-	// Make sure to get the correct tab selected.
-	if ($context['report']['closed'])
-		$context[$context['moderation_menu_name']]['current_subsection'] = 'closed';
-
-	// Finally we are done :P
-	loadTemplate('ModerationCenter');
-	$context['page_title'] = sprintf($txt['mc_viewmodreport'], $context['report']['subject'], $context['report']['author']['name']);
-	$context['sub_template'] = 'viewmodreport';
-}
-
 function MemberReport()
 {
 	global $user_info, $context, $sourcedir, $scripturl, $txt, $smcFunc;

+ 24 - 3
Sources/ReportToMod.php

@@ -1,7 +1,7 @@
 <?php
 
 /**
- * The functions in this file deal with reporting posts or porfiles to mods and admins
+ * The functions in this file deal with reporting posts or profiles to mods and admins
  * Simple Machines Forum (SMF)
  *
  * @package SMF
@@ -25,9 +25,11 @@ if (!defined('SMF'))
  */
 function ReportToModerator()
 {
-	global $txt, $topic, $context, $smcFunc, $scripturl;
+	global $txt, $topic, $context, $smcFunc, $scripturl, $sourcedir;
+
 
 	$context['robot_no_index'] = true;
+	$context['comment_body'] = '';
 
 	// No guests!
 	is_not_guest();
@@ -39,8 +41,23 @@ function ReportToModerator()
 	elseif (isset($_REQUEST['u']))
 		isAllowedTo('report_user');
 
+	// Previewing or modifying?
+	if (isset($_POST['preview']) && !isset($_POST['save']))
+	{
+		require_once($sourcedir . '/Subs-Post.php');
+
+		// Set up the preview message.
+		$context['preview_message'] = $smcFunc['htmlspecialchars']($_POST['comment'], ENT_QUOTES);
+		preparsecode($context['preview_message']);
+
+		// We censor for your protection...
+		censorText($context['preview_message']);
+
+		$context['comment_body'] = !empty($_POST['comment']) ? trim($_POST['comment']) : '';
+	}
+
 	// If they're posting, it should be processed by ReportToModerator2.
-	if ((isset($_POST[$context['session_var']]) || isset($_POST['save'])) && empty($context['post_errors']))
+	if ((isset($_POST[$context['session_var']]) || isset($_POST['save'])) && empty($context['post_errors']) && !isset($_POST['preview']))
 		ReportToModerator2();
 
 	// We need a message ID or user ID to check!
@@ -164,6 +181,9 @@ function ReportToModerator2()
 
 	require_once($sourcedir . '/Subs-Post.php');
 
+	// Prevent double submission of this form.
+	checkSubmitOnce('check');
+
 	// No errors, yet.
 	$post_errors = array();
 
@@ -174,6 +194,7 @@ function ReportToModerator2()
 	// Make sure we have a comment and it's clean.
 	if (!isset($_POST['comment']) || $smcFunc['htmltrim']($_POST['comment']) === '')
 		$post_errors[] = 'no_comment';
+
 	$poster_comment = strtr($smcFunc['htmlspecialchars']($_POST['comment']), array("\r" => '', "\t" => ''));
 
 	if ($smcFunc['strlen']($poster_comment) > 254)

+ 543 - 0
Sources/ReportedPosts.php

@@ -0,0 +1,543 @@
+<?php
+
+/**
+ * Handles reported posts and moderation comments.
+ *
+ * Simple Machines Forum (SMF)
+ *
+ * @package SMF
+ * @author Simple Machines http://www.simplemachines.org
+ * @copyright 2014 Simple Machines and individual contributors
+ * @license http://www.simplemachines.org/about/smf/license.php BSD
+ *
+ * @version 2.1 Alpha 1
+ */
+
+if (!defined('SMF'))
+	die('No direct access...');
+
+/**
+ * Sets and call a function based on the given subaction. Acts as a dispatcher function.
+ * It requires the moderate_forum permission.
+ *
+ * @uses ModerationCenter template.
+ * @uses ModerationCenter language file.
+ *
+ */
+function ReportedPosts()
+{
+	global $txt, $context, $scripturl, $user_info, $smcFunc;
+	global $sourcedir;
+
+	loadLanguage('ModerationCenter');
+	loadTemplate('ReportedPosts');
+
+	// We need this little rough gem.
+	require_once($sourcedir . '/Subs-ReportedPosts.php');
+
+	// Do we need to show a confirmation message?
+	$context['report_post_action'] = !empty($_SESSION['rc_confirmation']) ? $_SESSION['rc_confirmation'] : array();
+	unset($_SESSION['rc_confirmation']);
+
+	// Set up the comforting bits...
+	$context['page_title'] = $txt['mc_reported_posts'];
+
+	// Put the open and closed options into tabs, because we can...
+	$context[$context['moderation_menu_name']]['tab_data'] = array(
+		'title' => $txt['mc_reported_posts'],
+		'help' => '',
+		'description' => $txt['mc_reported_posts_desc'],
+	);
+
+	// This comes under the umbrella of moderating posts.
+	if ($user_info['mod_cache']['bq'] == '0=1')
+		isAllowedTo('moderate_forum');
+
+	$sub_actions = array(
+		'show' => 'ShowReports',
+		'closed' => 'ShowClosedReports',
+		'handle' => 'HandleReport', // Deals with closing/opening reports.
+		'details' => 'ReportDetails', // Shows a single report and its comments.
+		'handlecomment' => 'HandleComment', // CRUD actions for moderator comments.
+		'editcomment' => 'EditComment',
+	);
+
+	// Go ahead and add your own sub-actions.
+	call_integration_hook('integrate_reported_posts', array(&$sub_actions));
+
+	// By default we call the open sub-action.
+	if (isset($_REQUEST['sa']) && isset($sub_actions[$_REQUEST['sa']]))
+		$context['sub_action'] = $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_REQUEST['sa']), ENT_QUOTES);
+
+	else
+		$context['sub_action'] = 'show';
+
+	// Hi Ho Silver Away!
+	$sub_actions[$context['sub_action']]();
+}
+
+/**
+ * Shows all currently open reported posts.
+ * Handles closing multiple reports
+ *
+ */
+function ShowReports()
+{
+	global $context, $txt, $scripturl;
+
+	// Showing closed or open ones? regardless, turn this to an integer for better handling.
+	$context['view_closed'] = 0;
+
+	// Call the right template.
+	$context['sub_template'] = 'reported_posts';
+	$context['start'] = (int) isset($_GET['start']) ? $_GET['start'] : 0;
+
+	// Before anything, we need to know just how many reports do we have.
+	$context['total_reports'] = countReports($context['view_closed']);
+
+	// Just how many items are we showing per page?
+	$context['reports_how_many'] = 10;
+
+	// So, that means we can have pagination, yes?
+	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=reports;sa=show', $context['start'], $context['total_reports'], $context['reports_how_many']);
+
+	// Get the reports at once!
+	$context['reports'] = getReports($context['view_closed']);
+
+	// Are we closing multiple reports?
+	if (isset($_POST['close']) && isset($_POST['close_selected']))
+	{
+		checkSession('post');
+		validateToken('mod-report-close-all');
+
+		// All the ones to update...
+		$toClose = array();
+		foreach ($_POST['close'] as $rid)
+			$toClose[] = (int) $rid;
+
+		if (!empty($toClose))
+			updateReport('closed', 1, $toClose);
+
+		// Set the confirmation message.
+		$_SESSION['rc_confirmation'] = 'close_all';
+
+		// Force a page refresh.
+		redirectexit($scripturl . '?action=moderate;area=reports');
+	}
+
+	// Show a confirmation if the user wants to disregard a report.
+	if (!$context['view_closed'])
+		addInlineJavascript('
+	$(\'.delete_message\').on(\'click\', function(){
+			return confirm('. JavaScriptEscape($txt['mc_reportedp_delete_confirm']) .');
+	});
+	$(\'.report_ignore\').on(\'click\', function(){
+		// Need to make sure to only show this when ignoring.
+		if ($(this).data(\'ignore\') == \'1\'){
+			return confirm('. JavaScriptEscape($txt['mc_reportedp_ignore_confirm']) .');
+		}
+	});', true);
+
+	createToken('mod-report-close-all');
+	createToken('mod-report-ignore', 'get');
+	createToken('mod-report-closed', 'get');
+}
+
+/**
+ * Shows all currently closed reported posts.
+ *
+ */
+function ShowClosedReports()
+{
+	global $context, $txt, $scripturl;
+
+	// Showing closed ones.
+	$context['view_closed'] = 1;
+
+	// Call the right template.
+	$context['sub_template'] = 'reported_posts';
+	$context['start'] = (int) isset($_GET['start']) ? $_GET['start'] : 0;
+
+	// Before anything, we need to know just how many reports do we have.
+	$context['total_reports'] = countReports($context['view_closed']);
+
+	// Just how many items are we showing per page?
+	$context['reports_how_many'] = 10;
+
+	// So, that means we can have pagination, yes?
+	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=reports;sa=closed', $context['start'], $context['total_reports'], $context['reports_how_many']);
+
+	// Get the reports at once!
+	$context['reports'] = getReports($context['view_closed']);
+
+	// Show a confirmation if the user wants to disregard a report.
+	addInlineJavascript('
+	$(\'.delete_message\').on(\'click\', function(){
+			return confirm('. JavaScriptEscape($txt['mc_reportedp_delete_confirm']) .');
+	});
+	$(\'.report_ignore\').on(\'click\', function(){
+		// Need to make sure to only show this when ignoring.
+		if ($(this).data(\'ignore\') == \'1\'){
+			return confirm('. JavaScriptEscape($txt['mc_reportedp_ignore_confirm']) .');
+		}
+	});', true);
+
+	createToken('mod-report-ignore', 'get');
+	createToken('mod-report-closed', 'get');
+}
+
+/**
+ * Shows detailed information about a report. such as report comments and moderator comments.
+ * Shows a list of moderation actions for the specific report.
+ *
+ */
+function ReportDetails()
+{
+	global $user_info, $context, $sourcedir, $scripturl, $txt;
+	global $smcFunc;
+
+	$report = array();
+	$reportComments = array();
+
+	// Have to at least give us something to work with.
+	if (empty($_REQUEST['rid']))
+		fatal_lang_error('mc_reportedp_none_found');
+
+	// Integers only please
+	$report_id = (int) $_REQUEST['rid'];
+
+	// Get the report details.
+	$report = getReportDetails($report_id);
+
+	if(!$report)
+		fatal_lang_error('mc_no_modreport_found');
+
+	// Build the report data.
+	$context['report'] = array(
+		'id' => $report['id_report'],
+		'topic_id' => $report['id_topic'],
+		'board_id' => $report['id_board'],
+		'message_id' => $report['id_msg'],
+		'message_href' => $scripturl . '?msg=' . $report['id_msg'],
+		'message_link' => '<a href="' . $scripturl . '?msg=' . $report['id_msg'] . '">' . $report['subject'] . '</a>',
+		'report_href' => $scripturl . '?action=moderate;area=reports;rid=' . $report['id_report'],
+		'author' => array(
+			'id' => $report['id_author'],
+			'name' => $report['author_name'],
+			'link' => $report['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $report['id_author'] . '">' . $report['author_name'] . '</a>' : $report['author_name'],
+			'href' => $scripturl . '?action=profile;u=' . $report['id_author'],
+		),
+		'comments' => array(),
+		'mod_comments' => array(),
+		'time_started' => timeformat($report['time_started']),
+		'last_updated' => timeformat($report['time_updated']),
+		'subject' => $report['subject'],
+		'body' => parse_bbc($report['body']),
+		'num_reports' => $report['num_reports'],
+		'closed' => $report['closed'],
+		'ignore' => $report['ignore_all']
+	);
+
+	$reportComments = getReportComments($report_id);
+
+	if (!empty($reportComments))
+		$context['report'] = array_merge($context['report'], $reportComments);
+
+	// What have the other moderators done to this message?
+	require_once($sourcedir . '/Modlog.php');
+	require_once($sourcedir . '/Subs-List.php');
+	loadLanguage('Modlog');
+
+	// This is all the information from the moderation log.
+	$listOptions = array(
+		'id' => 'moderation_actions_list',
+		'title' => $txt['mc_modreport_modactions'],
+		'items_per_page' => 15,
+		'no_items_label' => $txt['modlog_no_entries_found'],
+		'base_href' => $scripturl . '?action=moderate;area=reports;sa=details;rid=' . $context['report']['id'],
+		'default_sort_col' => 'time',
+		'get_items' => array(
+			'function' => 'list_getModLogEntries',
+			'params' => array(
+				'lm.id_topic = {int:id_topic}',
+				array('id_topic' => $context['report']['topic_id']),
+				1,
+			),
+		),
+		'get_count' => array(
+			'function' => 'list_getModLogEntryCount',
+			'params' => array(
+				'lm.id_topic = {int:id_topic}',
+				array('id_topic' => $context['report']['topic_id']),
+				1,
+			),
+		),
+		// This assumes we are viewing by user.
+		'columns' => array(
+			'action' => array(
+				'header' => array(
+					'value' => $txt['modlog_action'],
+				),
+				'data' => array(
+					'db' => 'action_text',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'lm.action',
+					'reverse' => 'lm.action DESC',
+				),
+			),
+			'time' => array(
+				'header' => array(
+					'value' => $txt['modlog_date'],
+				),
+				'data' => array(
+					'db' => 'time',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'lm.log_time',
+					'reverse' => 'lm.log_time DESC',
+				),
+			),
+			'moderator' => array(
+				'header' => array(
+					'value' => $txt['modlog_member'],
+				),
+				'data' => array(
+					'db' => 'moderator_link',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'mem.real_name',
+					'reverse' => 'mem.real_name DESC',
+				),
+			),
+			'position' => array(
+				'header' => array(
+					'value' => $txt['modlog_position'],
+				),
+				'data' => array(
+					'db' => 'position',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'mg.group_name',
+					'reverse' => 'mg.group_name DESC',
+				),
+			),
+			'ip' => array(
+				'header' => array(
+					'value' => $txt['modlog_ip'],
+				),
+				'data' => array(
+					'db' => 'ip',
+					'class' => 'smalltext',
+				),
+				'sort' => array(
+					'default' => 'lm.ip',
+					'reverse' => 'lm.ip DESC',
+				),
+			),
+		),
+	);
+
+	// Create the watched user list.
+	createList($listOptions);
+
+	// Make sure to get the correct tab selected.
+	if ($context['report']['closed'])
+		$context[$context['moderation_menu_name']]['current_subsection'] = 'closed';
+
+	addInlineJavascript('
+	$(\'.deleteModComment\').on(\'click\', function() {
+		return confirm('. (JavaScriptEscape($txt['mc_reportedp_delete_confirm'])) .');
+});', true);
+
+	// Finally we are done :P
+	$context['page_title'] = sprintf($txt['mc_viewmodreport'], $context['report']['subject'], $context['report']['author']['name']);
+	$context['sub_template'] = 'viewmodreport';
+
+	// We can ignore a report from this page too so show the confirmation on here as well.
+	addInlineJavascript('
+	$(\'.report_ignore\').on(\'click\', function(){
+		// Need to make sure to only show this when ignoring.
+		if ($(this).data(\'ignore\') == \'1\'){
+			return confirm('. JavaScriptEscape($txt['mc_reportedp_ignore_confirm']) .');
+		}
+	});', true);
+
+	createToken('mod-reportC-add');
+	createToken('mod-reportC-delete', 'get');
+
+	// We can "un-disregard" and close a report from here so add their respective tokens.
+	createToken('mod-report-ignore', 'get');
+	createToken('mod-report-closed', 'get');
+}
+
+/**
+ * Creates/Deletes moderator comments.
+ *
+ */
+function HandleComment()
+{
+	global $smcFunc, $scripturl, $user_info;
+
+	$comment = array();
+
+	// The report ID is a must.
+	if (empty($_REQUEST['rid']))
+		fatal_lang_error('mc_reportedp_none_found');
+
+	// Integers only please.
+	$report_id = (int) $_REQUEST['rid'];
+
+	// If they are adding a comment then... add a comment.
+	if (isset($_POST['add_comment']) && !empty($_POST['mod_comment']))
+	{
+		checkSession();
+		validateToken('mod-reportC-add');
+
+		$new_comment = trim($smcFunc['htmlspecialchars']($_POST['mod_comment']));
+
+		saveModComment($report_id, array($report_id, $new_comment, time()));
+
+		// Everything went better than expected!
+		$_SESSION['rc_confirmation'] = 'message_saved';
+	}
+
+	// Deleting a comment?
+	if (isset($_REQUEST['delete']) && isset($_REQUEST['mid']))
+	{
+		checkSession('get');
+		validateToken('mod-reportC-delete', 'get');
+
+		if (empty($_REQUEST['mid']))
+			fatal_lang_error('mc_reportedp_comment_none_found');
+
+		$comment_id = (int) $_REQUEST['mid'];
+
+		// We need to verify some data, so lets load the comment details once more!
+		$comment = getCommentModDetails($comment_id);
+
+		// Perhaps somebody else already deleted this fine gem...
+		if (empty($comment))
+			fatal_lang_error('report_action_message_delete_issue');
+
+		// Can you actually do this?
+		$comment_owner = $user_info['id'] == $context['comment']['id_member'];
+
+		// Nope! sorry.
+		if (!allowedTo('admin_forum') || !$comment_owner)
+			fatal_lang_error('report_action_message_delete_cannot');
+
+		// All good!
+		deleteModComment($comment_id);
+
+		// Tell them the message was deleted.
+		$_SESSION['rc_confirmation'] = 'message_deleted';
+	}
+
+	//Redirect to prevent double submission.
+	redirectexit($scripturl . '?action=moderate;area=reports;sa=details;rid=' . $report_id);
+}
+
+/**
+ * Shows a textarea for editing a moderator comment.
+ * Handles the edited comment and stores it on the DB.
+ *
+ */
+function EditComment()
+{
+	global $smcFunc, $context, $txt, $scripturl, $user_info;
+
+	$comment = array();
+
+	checkSession(isset($_REQUEST['save']) ? 'post' : 'get');
+
+	// The report ID is a must.
+	if (empty($_REQUEST['rid']))
+		fatal_lang_error('mc_reportedp_none_found');
+
+	if (empty($_REQUEST['mid']))
+		fatal_lang_error('mc_reportedp_comment_none_found');
+
+	// Integers only please.
+	$context['report_id'] = (int) $_REQUEST['rid'];
+	$context['comment_id'] = (int) $_REQUEST['mid'];
+
+	$context['comment'] = getCommentModDetails($context['comment_id']);
+
+	if (empty($context['comment']))
+		fatal_lang_error('mc_reportedp_comment_none_found');
+
+	// Set up the comforting bits...
+	$context['page_title'] = $txt['mc_reported_posts'];
+	$context['sub_template'] = 'edit_comment';
+
+	if (isset($_REQUEST['save']) && isset($_POST['edit_comment']) && !empty($_POST['mod_comment']))
+	{
+		validateToken('mod-reportC-edit');
+
+		// Make sure there is some data to edit on the DB.
+		if (empty($context['comment']))
+			fatal_lang_error('report_action_message_edit_issue');
+
+		// Still there, good, now lets see if you can actually edit it...
+		$comment_owner = $user_info['id'] == $context['comment']['id_member'];
+
+		// So, you aren't neither an admin or the comment owner huh? that's too bad.
+		if (!allowedTo('admin_forum') || !$comment_owner)
+			fatal_lang_error('report_action_message_edit_cannot');
+
+		// All good!
+		$edited_comment = trim($smcFunc['htmlspecialchars']($_POST['mod_comment']));
+
+		editModComment($context['comment_id'], $edited_comment);
+
+		$_SESSION['rc_confirmation'] = 'message_edited';
+
+		redirectexit($scripturl . '?action=moderate;area=reports;sa=details;rid=' . $context['report_id']);
+	}
+
+	createToken('mod-reportC-edit');
+}
+
+/**
+ * Performs closing/ignoring actions for a given report.
+ *
+ */
+function HandleReport()
+{
+	global $scripturl;
+
+	checkSession('get');
+
+	// We need to do something!
+	if (empty($_GET['rid']) && (!isset($_GET['ignore']) || !isset($_GET['closed'])))
+		fatal_lang_error('mc_reportedp_none_found');
+
+	// What are we gonna do?
+	$action = isset($_GET['ignore']) ? 'ignore' : 'closed';
+
+	validateToken('mod-report-'. $action, 'get');
+
+	// Are we disregarding or "un-disregarding"? "un-disregarding" thats a funny word!
+	$value = (int) $_GET[$action];
+
+	// Figuring out.
+	$message = $action == 'ignore' ? ($value ? 'ignore' : 'unignore') : ($value ? 'close' : 'open');
+
+	// Integers only please.
+	$report_id = (int) $_REQUEST['rid'];
+
+	// Update the DB entry
+	updateReport($action, $value, $report_id);
+
+	// So, time to show a confirmation message, lets do some trickery!
+	$_SESSION['rc_confirmation'] = $message;
+
+	// Done!
+	redirectexit($scripturl . '?action=moderate;area=reports');
+}
+?>

+ 1 - 1
Sources/Security.php

@@ -493,7 +493,7 @@ function banPermissions()
 		$context['open_mod_reports'] = $_SESSION['rc']['reports'];
 	elseif ($_SESSION['mc']['bq'] != '0=1')
 	{
-		require_once($sourcedir . '/ModerationCenter.php');
+		require_once($sourcedir . '/Subs-ReportedPosts.php');
 		recountOpenReports();
 	}
 	else

+ 529 - 0
Sources/Subs-ReportedPosts.php

@@ -0,0 +1,529 @@
+<?php
+
+/**
+ * Perform CRUD actions for reported posts and moderation comments.
+ *
+ * Simple Machines Forum (SMF)
+ *
+ * @package SMF
+ * @author Simple Machines http://www.simplemachines.org
+ * @copyright 2014 Simple Machines and individual contributors
+ * @license http://www.simplemachines.org/about/smf/license.php BSD
+ *
+ * @version 2.1 Alpha 1
+ */
+
+if (!defined('SMF'))
+	die('No direct access...');
+
+/**
+ * Updates a report with the given parameters. Logs each action via logAction()
+ *
+ * @param string $action The action to perform. Accepts "closed" and "ignore".
+ * @param integer $value The new value to update.
+ * @params integer|array $report_id The affected report(s).
+ */
+function updateReport($action, $value, $report_id)
+{
+	global $smcFunc, $user_info, $context;
+
+	// Don't bother.
+	if (empty($action) || empty($report_id))
+		return false;
+
+	// Add the "_all" thingy.
+	if ($action == 'ignore')
+		$action = 'ignore_all';
+
+	// Update the report...
+	$smcFunc['db_query']('', '
+		UPDATE {db_prefix}log_reported
+		SET  {raw:action} = {string:value}
+		'. (is_array($report_id) ? 'WHERE id_report IN ({array_int:id_report})' : 'WHERE id_report = {int:id_report}') .'
+			AND ' . $user_info['mod_cache']['bq'],
+		array(
+			'action' => $action,
+			'value' => $value,
+			'id_report' => $report_id,
+		)
+	);
+
+	// From now on, lets work with arrays, makes life easier.
+	$report_id = (array) $report_id;
+
+	// Get the board, topic and message for this report
+	$request = $smcFunc['db_query']('', '
+		SELECT id_board, id_topic, id_msg, id_report
+		FROM {db_prefix}log_reported
+		WHERE id_report IN ({array_int:id_report})',
+		array(
+			'id_report' => $report_id,
+		)
+	);
+
+	// Set up the data for the log...
+	$extra = array();
+
+	while ($row = $smcFunc['db_fetch_assoc']($request))
+		$extra[$row['id_report']] = array(
+			'report' => $row['id_report'],
+			'board' => $row['id_board'],
+			'message' => $row['id_msg'],
+			'topic' => $row['id_topic'],
+		);
+
+	$smcFunc['db_free_result']($request);
+
+	// Back to "ignore".
+	if ($action == 'ignore_all')
+		$action = 'ignore';
+
+	$log_report = $action == 'ignore' ? (!empty($value) ? 'ignore' : 'unignore') : (!empty($value) ? 'close' : 'open');
+
+	// Log this action.
+	if (!empty($extra))
+		foreach ($extra as $report)
+			logAction($log_report . '_report', $report);
+
+	// Time to update.
+	updateSettings(array('last_mod_report_action' => time()));
+	recountOpenReports();
+}
+
+/**
+ * Counts how many reports are in total. Used for creating pagination.
+ *
+ * @param int $closed 1 for counting closed reports, 0 for open ones.
+ * @return integer How many reports.
+
+ */
+function countReports($closed = 0)
+{
+	global $smcFunc, $user_info;
+
+	$total_reports = 0;
+
+	// How many entries are we viewing?
+	$request = $smcFunc['db_query']('', '
+		SELECT COUNT(*)
+		FROM {db_prefix}log_reported AS lr
+		WHERE lr.closed = {int:view_closed}
+			AND ' . ($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']),
+		array(
+			'view_closed' => (int) $closed,
+		)
+	);
+	list ($total_reports) = $smcFunc['db_fetch_row']($request);
+	$smcFunc['db_free_result']($request);
+
+	return $total_reports;
+}
+
+/**
+ * Get all possible reports the current user can see.
+ *
+ * @param int $closed 1 for closed reports, 0 for open ones.
+ * @return array the reports data with the report ID as key.
+ */
+function getReports($closed = 0)
+{
+	global $smcFunc, $context, $user_info, $scripturl;
+
+	// Lonely, standalone var.
+	$reports = array();
+
+	// By George, that means we in a position to get the reports, golly good.
+	$request = $smcFunc['db_query']('', '
+		SELECT lr.id_report, lr.id_msg, lr.id_topic, lr.id_board, lr.id_member, lr.subject, lr.body,
+			lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
+			IFNULL(mem.real_name, lr.membername) AS author_name, IFNULL(mem.id_member, 0) AS id_author
+		FROM {db_prefix}log_reported AS lr
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
+		WHERE lr.closed = {int:view_closed}
+			AND ' . ($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']) . '
+		ORDER BY lr.time_updated DESC
+		LIMIT ' . $context['start'] . ', 10',
+		array(
+			'view_closed' => (int) $closed,
+		)
+	);
+
+	$report_ids = array();
+	$report_boards_ids = array();
+	for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i++)
+	{
+		$report_ids[] = $row['id_report'];
+		$report_boards_ids[] = $row['id_board'];
+		$reports[$row['id_report']] = array(
+			'id' => $row['id_report'],
+			'alternate' => $i % 2,
+			'topic' => array(
+				'id' => $row['id_topic'],
+				'id_msg' => $row['id_msg'],
+				'id_board' => $row['id_board'],
+				'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
+			),
+			'report_href' => $scripturl . '?action=moderate;area=reports;sa=details;rid=' . $row['id_report'],
+			'author' => array(
+				'id' => $row['id_author'],
+				'name' => $row['author_name'],
+				'link' => $row['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_author'] . '">' . $row['author_name'] . '</a>' : $row['author_name'],
+				'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
+			),
+			'comments' => array(),
+			'time_started' => timeformat($row['time_started']),
+			'last_updated' => timeformat($row['time_updated']),
+			'subject' => $row['subject'],
+			'body' => parse_bbc($row['body']),
+			'num_reports' => $row['num_reports'],
+			'closed' => $row['closed'],
+			'ignore' => $row['ignore_all']
+		);
+	}
+	$smcFunc['db_free_result']($request);
+
+	// Get the names of boards those topics are in. Slightly faster this way.
+	if (!empty($report_boards_ids))
+	{
+		$report_boards_ids = array_unique($report_boards_ids);
+		$board_names = array();
+		$request = $smcFunc['db_query']('', '
+			SELECT id_board, name
+			FROM {db_prefix}boards
+			WHERE id_board IN ({array_int:boards})',
+			array(
+				'boards' => $report_boards_ids,
+			)
+		);
+
+		while ($row = $smcFunc['db_fetch_assoc']($request))
+			$board_names[$row['id_board']] = $row['name'];
+
+		$smcFunc['db_free_result']($request);
+
+		foreach ($reports as $id_report => $report)
+			if (!empty($board_names[$report['topic']['id_board']]))
+				$reports[$id_report]['topic']['board_name'] = $board_names[$report['topic']['id_board']];
+	}
+
+	// Now get all the people who reported it.
+	if (!empty($report_ids))
+	{
+		$request = $smcFunc['db_query']('', '
+			SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment,
+				IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lrc.membername) AS reporter
+			FROM {db_prefix}log_reported_comments AS lrc
+				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
+			WHERE lrc.id_report IN ({array_int:report_list})',
+			array(
+				'report_list' => $report_ids,
+			)
+		);
+		while ($row = $smcFunc['db_fetch_assoc']($request))
+		{
+			$reports[$row['id_report']]['comments'][] = array(
+				'id' => $row['id_comment'],
+				'message' => $row['comment'],
+				'time' => timeformat($row['time_sent']),
+				'member' => array(
+					'id' => $row['id_member'],
+					'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
+					'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
+					'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
+				),
+			);
+		}
+		$smcFunc['db_free_result']($request);
+	}
+
+	// Get the boards where the current user can remove any message.
+	$context['report_remove_any_boards'] = $user_info['is_admin'] ? $report_boards_ids : array_intersect($report_boards_ids, boardsAllowedTo('remove_any'));
+	$context['report_manage_bans'] = allowedTo('manage_bans');
+
+	return $reports;
+}
+
+/**
+ * Recount all open reports. Sets a SESSION var with the updated info.
+ *
+ * @return int the update open report count.
+ */
+function recountOpenReports()
+{
+	global $user_info, $smcFunc;
+
+	$request = $smcFunc['db_query']('', '
+		SELECT COUNT(*)
+		FROM {db_prefix}log_reported
+		WHERE ' . $user_info['mod_cache']['bq'] . '
+			AND closed = {int:not_closed}
+			AND ignore_all = {int:not_ignored}',
+		array(
+			'not_closed' => 0,
+			'not_ignored' => 0,
+		)
+	);
+	list ($open_reports) = $smcFunc['db_fetch_row']($request);
+	$smcFunc['db_free_result']($request);
+
+	$_SESSION['rc'] = array(
+		'id' => $user_info['id'],
+		'time' => time(),
+		'reports' => $open_reports,
+	);
+
+	return $open_reports;
+}
+
+/**
+ * Gets additional information for a specific report.
+ *
+ * @param int $report_id The report ID to get the info from.
+ * @return array|bool the report data. Boolean false if no report_id was provided.
+ */
+function getReportDetails($report_id)
+{
+	global $smcFunc, $user_info;
+
+	if (empty($report_id))
+		return false;
+
+	// Get the report details, need this so we can limit access to a particular board.
+	$request = $smcFunc['db_query']('', '
+		SELECT lr.id_report, lr.id_msg, lr.id_topic, lr.id_board, lr.id_member, lr.subject, lr.body,
+			lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
+			IFNULL(mem.real_name, lr.membername) AS author_name, IFNULL(mem.id_member, 0) AS id_author
+		FROM {db_prefix}log_reported AS lr
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
+		WHERE lr.id_report = {int:id_report}
+			AND ' . ($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']) . '
+		LIMIT 1',
+		array(
+			'id_report' => $report_id,
+		)
+	);
+
+	// So did we find anything?
+	if (!$smcFunc['db_num_rows']($request))
+		return false;
+
+	// Woohoo we found a report and they can see it!
+	$row = $smcFunc['db_fetch_assoc']($request);
+	$smcFunc['db_free_result']($request);
+
+	return $row;
+}
+
+/**
+ * Gets both report comments as well as any moderator comment.
+ *
+ * @param int $report_id The report ID to get the info from.
+ * @return array|bool an associative array with 2 keys comments and mod_comments. Boolean false if no report_id was provided.
+ */
+function getReportComments($report_id)
+{
+	global $smcFunc, $scripturl;
+
+	if (empty($report_id))
+		return false;
+
+	$report = array(
+		'comments' => array(),
+		'mod_comments' => array()
+	);
+
+	// So what bad things do the reporters have to say about it?
+	$request = $smcFunc['db_query']('', '
+		SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment, lrc.member_ip,
+			IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lrc.membername) AS reporter
+		FROM {db_prefix}log_reported_comments AS lrc
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
+		WHERE lrc.id_report = {int:id_report}',
+		array(
+			'id_report' => $report_id,
+		)
+	);
+
+	while ($row = $smcFunc['db_fetch_assoc']($request))
+	{
+		$report['comments'][] = array(
+			'id' => $row['id_comment'],
+			'message' => strtr($row['comment'], array("\n" => '<br>')),
+			'time' => timeformat($row['time_sent']),
+			'member' => array(
+				'id' => $row['id_member'],
+				'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
+				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
+				'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
+				'ip' => !empty($row['member_ip']) && allowedTo('moderate_forum') ? '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>' : '',
+			),
+		);
+	}
+	$smcFunc['db_free_result']($request);
+
+	// Hang about old chap, any comments from moderators on this one?
+	$request = $smcFunc['db_query']('', '
+		SELECT lc.id_comment, lc.id_notice, lc.log_time, lc.body,
+			IFNULL(mem.id_member, 0) AS id_member, IFNULL(mem.real_name, lc.member_name) AS moderator
+		FROM {db_prefix}log_comments AS lc
+			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
+		WHERE lc.id_notice = {int:id_report}
+			AND lc.comment_type = {literal:reportc}',
+		array(
+			'id_report' => $report_id,
+		)
+	);
+
+	while ($row = $smcFunc['db_fetch_assoc']($request))
+	{
+		$report['mod_comments'][] = array(
+			'id' => $row['id_comment'],
+			'message' => parse_bbc($row['body']),
+			'time' => timeformat($row['log_time']),
+			'can_edit' => allowedTo('admin_forum') || (($user_info['id'] == $row['id_member']) && allowedTo('moderate_forum')),
+			'member' => array(
+				'id' => $row['id_member'],
+				'name' => $row['moderator'],
+				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['moderator'] . '</a>' : $row['moderator'],
+				'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
+			),
+		);
+	}
+
+	$smcFunc['db_free_result']($request);
+
+	return $report;
+}
+
+/**
+ * Gets specific details about a moderator comment. It also adds a permission for editing/deleting the comment,
+ * by default only admins and the author of the comment can edit/delete it.
+ *
+ * @param int $comment_id The moderator comment ID to get the info from.
+ * @return array|bool an array with the fetched data. Boolean false if no report_id was provided.
+ */
+function getCommentModDetails($comment_id)
+{
+	global $smcFunc, $user_info;
+
+	$comment = array();
+
+	if (empty($comment_id))
+		return false;
+
+	$request = $smcFunc['db_query']('', '
+		SELECT id_comment, id_notice, log_time, body, id_member
+		FROM {db_prefix}log_comments
+		WHERE id_comment = {int:id_comment}
+			AND comment_type = {literal:reportc}',
+		array(
+			'id_comment' => $comment_id,
+		)
+	);
+
+	$comment = $smcFunc['db_fetch_assoc']($request);
+
+	$smcFunc['db_free_result']($request);
+
+	// Add the permission
+	if (!empty($comment))
+		$comment['can_edit'] = allowedTo('admin_forum') || (($user_info['id'] == $comment['id_member']) && allowedTo('moderate_forum'));
+
+	return $comment;
+}
+
+/**
+ * Inserts a new moderator comment to the DB.
+ *
+ * @param int $report_id The report ID is used to fire a notification about the event.
+ * @param array $data a formatted array of data to be inserted. Should be already properly sanitized.
+ * @return bool  Boolean false if no data was provided.
+ */
+function saveModComment($report_id, $data)
+{
+	global $smcFunc, $user_info;
+
+	if (empty($data))
+		return false;
+
+	$data = array_merge(array($user_info['id'], $user_info['name'], 'reportc', ''), $data);
+
+	$smcFunc['db_insert']('',
+		'{db_prefix}log_comments',
+		array(
+			'id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'recipient_name' => 'string',
+			'id_notice' => 'int', 'body' => 'string', 'log_time' => 'int',
+		),
+		$data,
+		array('id_comment')
+	);
+	$last_comment = $smcFunc['db_insert_id']('{db_prefix}log_comments', 'id_comment');
+
+	$report = getReportDetails($report_id);
+
+	// And get ready to notify people.
+	if (!empty($report))
+		$smcFunc['db_insert']('insert',
+			'{db_prefix}background_tasks',
+			array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'),
+			array('$sourcedir/tasks/MsgReportReply-Notify.php', 'MsgReportReply_Notify_Background', serialize(array(
+				'report_id' => $report_id,
+				'comment_id' => $last_comment,
+				'msg_id' => $report['id_msg'],
+				'topic_id' => $report['id_topic'],
+				'board_id' => $report['id_board'],
+				'sender_id' => $user_info['id'],
+				'sender_name' => $user_info['name'],
+				'time' => time(),
+			)), 0),
+			array('id_task')
+		);
+}
+
+/**
+ * Saves the new information whenever a moderator comment is edited.
+ *
+ * @param int $comment_id The edited moderator comment ID.
+ * @param array $data The new data to de inserted. Should be already properly sanitized.
+ * @return bool  Boolean false if no data or no comment ID was provided.
+ */
+function editModComment($comment_id, $edited_comment)
+{
+	global $smcFunc;
+
+	if (empty($comment_id) || empty($edited_comment))
+		return false;
+
+	$smcFunc['db_query']('', '
+		UPDATE {db_prefix}log_comments
+		SET  body = {string:body}
+		WHERE id_comment = {int:id_comment}',
+		array(
+			'body' => $edited_comment,
+			'id_comment' => $comment_id,
+		)
+	);
+}
+
+/**
+ * Deletes a moderator comment from the DB.
+ *
+ * @param int $comment_id The moderator comment ID used to identify which report will be deleted.
+ * @return bool  Boolean false if no data was provided.
+ */
+function deleteModComment($comment_id)
+{
+	global $smcFunc;
+
+	if (empty($comment_id))
+		return false;
+
+	$smcFunc['db_query']('', '
+		DELETE FROM {db_prefix}log_comments
+		WHERE id_comment = {int:comment_id}',
+		array(
+			'comment_id' => $comment_id,
+		)
+	);
+}
+?>

+ 1 - 1
Sources/Subs.php

@@ -3966,7 +3966,7 @@ function setupMenuContext()
 
 	$total_mod_reports = 0;
 
-	if (!empty($user_info['mod_cache']) && $user_info['mod_cache']['bq'] != '0=1' && $context['open_mod_reports'] > 0)
+	if (!empty($user_info['mod_cache']) && $user_info['mod_cache']['bq'] != '0=1' && !empty($context['open_mod_reports']))
 	{
 		$total_mod_reports = $context['open_mod_reports'];
 		$context['menu_buttons']['moderate']['sub_buttons']['reports']['title'] .= ' <span class="amt">' . $context['open_mod_reports'] . '</span>';

+ 16 - 168
Themes/default/ModerationCenter.template.php

@@ -75,7 +75,7 @@ function template_group_requests_block()
 				</ul>
 			</div>
 		</div>
-		
+
 	<script><!-- // --><![CDATA[
 		var oGroupRequestsPanelToggle = new smc_Toggle({
 			bToggleEnabled: true,
@@ -109,73 +109,6 @@ function template_group_requests_block()
 	// ]]></script>';
 }
 
-// A block to show the current top reported posts.
-function template_reported_posts_block()
-{
-	global $context, $txt, $scripturl;
-
-	echo '
-		<div class="cat_bar">
-			<h3 class="catbg">
-				<span id="reported_posts_toggle" class="', !empty($context['admin_prefs']['mcrp']) ? 'toggle_down' : 'toggle_up', ' floatright" style="display: none;"></span>
-				<a href="', $scripturl, '?action=moderate;area=reports" id="reported_posts_link">', $txt['mc_recent_reports'], '</a>
-			</h3>
-		</div>
-		<div class="windowbg" id="reported_posts_panel">
-			<div class="content modbox">
-				<ul class="reset">';
-
-		foreach ($context['reported_posts'] as $report)
-			echo '
-					<li class="smalltext">
-						<a href="', $report['report_href'], '">', $report['subject'], '</a> ', $txt['mc_reportedp_by'], ' ', $report['author']['link'], '
-					</li>';
-
-		// Don't have any watched users right now?
-		if (empty($context['reported_posts']))
-			echo '
-					<li>
-						<strong class="smalltext">', $txt['mc_recent_reports_none'], '</strong>
-					</li>';
-
-		echo '
-				</ul>
-			</div>
-		</div>
-		
-	<script><!-- // --><![CDATA[
-		var oReportedPostsPanelToggle = new smc_Toggle({
-			bToggleEnabled: true,
-			bCurrentlyCollapsed: ', !empty($context['admin_prefs']['mcrp']) ? 'true' : 'false', ',
-			aSwappableContainers: [
-				\'reported_posts_panel\'
-			],
-			aSwapImages: [
-				{
-					sId: \'reported_posts_toggle\',
-					altExpanded: ', JavaScriptEscape($txt['hide']), ',
-					altCollapsed: ', JavaScriptEscape($txt['show']), '
-				}
-			],
-			aSwapLinks: [
-				{
-					sId: \'reported_posts_link\',
-					msgExpanded: ', JavaScriptEscape($txt['mc_recent_reports']), ',
-					msgCollapsed: ', JavaScriptEscape($txt['mc_recent_reports']), '
-				}
-			],
-			oThemeOptions: {
-				bUseThemeSettings: true,
-				sOptionName: \'admin_preferences\',
-				sSessionVar: smf_session_var,
-				sSessionId: smf_session_id,
-				sThemeId: \'1\',
-				sAdditionalVars: \';admin_key=mcrp\'
-			}
-		});
-	// ]]></script>';
-}
-
 function template_watched_users()
 {
 	global $context, $txt, $scripturl;
@@ -208,7 +141,7 @@ function template_watched_users()
 				</ul>
 			</div>
 		</div>
-		
+
 	<script><!-- // --><![CDATA[
 		var oWatchedUsersToggle = new smc_Toggle({
 			bToggleEnabled: true,
@@ -247,6 +180,15 @@ function template_notes()
 {
 	global $context, $txt, $scripturl;
 
+	// Let them know the action was a success.
+	if (!empty($context['report_post_action']))
+	{
+		echo '
+			<div class="infobox">
+				', $txt['report_action_'. $context['report_post_action']], '
+			</div>';
+	}
+
 	echo '
 		<div class="modnotes">
 			<form action="', $scripturl, '?action=moderate;area=index;modnote" method="post">
@@ -264,7 +206,7 @@ function template_notes()
 			// Cycle through the notes.
 			foreach ($context['notes'] as $note)
 				echo '
-							<li class="smalltext"><a href="', $note['delete_href'], '"><span class="generic_icons del_small"></span></a>', $note['time'] ,' <strong>', $note['author']['link'], ':</strong> ', $note['text'], '</li>';
+							<li class="smalltext"><a href="', $note['delete_href'], ';', $context['mod-modnote-del_token_var'], '=', $context['mod-modnote-del_token'], '" class="delete_modnote"><span class="generic_icons del_small"></span></a>', $note['time'] ,' <strong>', $note['author']['link'], ':</strong> ', $note['text'], '</li>';
 
 			echo '
 						</ul>
@@ -277,6 +219,7 @@ function template_notes()
 						<div class="floatleft post_note">
 						<input type="text" name="new_note" value="', $txt['mc_click_add_note'], '" style="width: 95%;" onclick="if (this.value == \'', $txt['mc_click_add_note'], '\') this.value = \'\';" class="input_text">
 						</div>
+						<input type="hidden" name="', $context['mod-modnote-add_token_var'], '" value="', $context['mod-modnote-add_token'], '">
 						<input type="submit" name="makenote" value="', $txt['mc_add_note'], '" class="button_submit">
 					</div>
 				</div>
@@ -285,102 +228,6 @@ function template_notes()
 		</div>';
 }
 
-function template_reported_posts()
-{
-	global $context, $txt, $scripturl;
-
-	// Let them know the action was a success.
-	if (!empty($context['report_post_action']) && !empty($txt['report_action_'. $context['report_post_action']]))
-	{
-		echo '
-			<div class="infobox">
-				', $txt['report_action_'. $context['report_post_action']], '
-			</div>';
-	}
-
-	echo '
-	<form id="reported_posts" action="', $scripturl, '?action=moderate;area=reports', $context['view_closed'] ? ';sa=closed' : '', ';start=', $context['start'], '" method="post" accept-charset="', $context['character_set'], '">
-		<div class="cat_bar">
-			<h3 class="catbg">
-				', $context['view_closed'] ? $txt['mc_reportedp_closed'] : $txt['mc_reportedp_active'], '
-			</h3>
-		</div>
-		<div class="pagesection">
-			<div class="pagelinks">', $context['page_index'], '</div>
-		</div>';
-
-	// Make the buttons.
-	$close_button = create_button('close.png', $context['view_closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', $context['view_closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', 'class="centericon"');
-	$details_button = create_button('details.png', 'mc_reportedp_details', 'mc_reportedp_details', 'class="centericon"');
-	$ignore_button = create_button('ignore.png', 'mc_reportedp_ignore', 'mc_reportedp_ignore', 'class="centericon"');
-	$unignore_button = create_button('ignore.png', 'mc_reportedp_unignore', 'mc_reportedp_unignore', 'class="centericon"');
-	$ban_button = create_button('close.png', 'mc_reportedp_ban', 'mc_reportedp_ban', 'class="centericon"');
-	$delete_button = create_button('delete.png', 'mc_reportedp_delete', 'mc_reportedp_delete', 'class="centericon"');
-
-	foreach ($context['reports'] as $report)
-	{
-		echo '
-		<div class="generic_list_wrapper ', $report['alternate'] ? 'windowbg' : 'windowbg2', '">
-			<div class="content">
-				<h5>
-					<strong>', !empty($report['topic']['board_name']) ? '<a href="' . $scripturl . '?board=' . $report['topic']['id_board'] . '.0">' . $report['topic']['board_name'] . '</a>' : '??', ' / <a href="', $report['topic']['href'], '">', $report['subject'], '</a></strong> ', $txt['mc_reportedp_by'], ' <strong>', $report['author']['link'], '</strong>
-				</h5>
-				<div class="smalltext">
-					', $txt['mc_reportedp_last_reported'], ': ', $report['last_updated'], '&nbsp;-&nbsp;';
-
-		// Prepare the comments...
-		$comments = array();
-		foreach ($report['comments'] as $comment)
-			$comments[$comment['member']['id']] = $comment['member']['link'];
-
-		echo '
-					', $txt['mc_reportedp_reported_by'], ': ', implode(', ', $comments), '
-				</div>
-				<hr>
-				', $report['body'], '
-				<br>
-				<ul class="quickbuttons">
-					<li><a href="', $report['report_href'], '">', $details_button, '</a></li>
-					<li><a href="', $scripturl, '?action=moderate;area=reports', $context['view_closed'] ? ';sa=closed' : '', ';ignore=', (int) !$report['ignore'], ';rid=', $report['id'], ';start=', $context['start'], ';', $context['session_var'], '=', $context['session_id'], '" ', !$report['ignore'] ? 'onclick="return confirm(\'' . $txt['mc_reportedp_ignore_confirm'] . '\');"' : '', '>', $report['ignore'] ? $unignore_button : $ignore_button, '</a></li>
-					<li><a href="', $scripturl, '?action=moderate;area=reports', $context['view_closed'] ? ';sa=closed' : '', ';close=', (int) !$report['closed'], ';rid=', $report['id'], ';start=', $context['start'], ';', $context['session_var'], '=', $context['session_id'], '">', $close_button, '</a></li>';
-
-		// Delete message button.
-		if (!$report['closed'] && (is_array($context['report_remove_any_boards']) && in_array($report['topic']['id_board'], $context['report_remove_any_boards'])))
-			echo '
-					<li><a href="', $scripturl, '?action=deletemsg;topic=', $report['topic']['id'] ,'.0;msg=', $report['topic']['id_msg'] ,';modcenter;', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(\'' , $txt['mc_reportedp_delete_confirm'] , '\');">', $delete_button, '</a></li>';
-
-		// Ban this user button.
-		if (!$report['closed'] && !empty($context['report_manage_bans']))
-			echo '
-					<li><a href="', $scripturl, '?action=admin;area=ban;sa=add', (!empty($report['author']['id']) ? ';u='. $report['author']['id'] : ';msg='. $report['topic']['id_msg']) ,';', $context['session_var'], '=', $context['session_id'], '">', $ban_button, '</a></li>';
-
-		echo '
-					<li>', !$context['view_closed'] ? '<input type="checkbox" name="close[]" value="' . $report['id'] . '" class="input_check">' : '', '</li>
-				</ul>
-			</div>
-		</div>';
-	}
-
-	// Were none found?
-	if (empty($context['reports']))
-		echo '
-		<div class="windowbg2">
-			<div class="content">
-				<p class="centertext">', $txt['mc_reportedp_none_found'], '</p>
-			</div>
-		</div>';
-
-	echo '
-		<div class="pagesection">
-			<div class="pagelinks floatleft">', $context['page_index'], '</div>
-			<div class="floatright">
-				', !$context['view_closed'] ? '<input type="submit" name="close_selected" value="' . $txt['mc_reportedp_close_selected'] . '" class="button_submit">' : '', '
-			</div>
-		</div>
-		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
-	</form>';
-}
-
 // Show a list of all the unapproved posts
 function template_unapproved_posts()
 {
@@ -473,6 +320,7 @@ function template_unapproved_posts()
 	</div>';
 }
 
+
 function template_viewmodreport()
 {
 	global $context, $scripturl, $txt;
@@ -730,8 +578,8 @@ function template_show_notice()
 		<div class="cat_bar">
 			<h3 class="catbg">', $txt['show_notice'], '</h3>
 		</div>
-		<div class="cat_bar">
-			<h3 class="catbg">', $txt['show_notice_subject'], ': ', $context['notice_subject'], '</h3>
+		<div class="title_bar">
+			<h3 class="titlebg">', $txt['show_notice_subject'], ': ', $context['notice_subject'], '</h3>
 		</div>
 		<div class="windowbg">
 			<div class="content">

+ 20 - 2
Themes/default/ReportToMod.template.php

@@ -16,10 +16,10 @@
 
 	The report sub template gets shown from:
 		'?action=reporttm;topic=##.##;msg=##'
-		'?action=reporttm;u=#'		
+		'?action=reporttm;u=#'
 	It should submit to:
 		'?action=reporttm;topic=' . $context['current_topic'] . '.' . $context['start']
-		'?action=reporttm;u=#'		
+		'?action=reporttm;u=#'
 	It only needs to send the following fields:
 		comment: an additional comment to give the moderator.
 		sc: the session id, or $context['session_id'].
@@ -29,6 +29,23 @@ function template_main()
 {
 	global $context, $txt, $scripturl;
 
+	// Want to see your master piece?
+	echo '
+	<div id="preview_section"', isset($context['preview_message']) ? '' : ' style="display: none;"', '>
+		<div class="cat_bar">
+			<h3 class="catbg">
+				<span>', $txt['preview'], '</span>
+			</h3>
+		</div>
+		<div class="windowbg">
+			<div class="content">
+				<div class="post" id="preview_body">
+					', empty($context['preview_message']) ? '<br>' : $context['preview_message'], '
+				</div>
+			</div>
+		</div>
+	</div><br>';
+
 	echo '
 	<div id="report_form">
 		<form action="', $context['submit_url'], '" method="post" accept-charset="', $context['character_set'], '">
@@ -75,6 +92,7 @@ function template_main()
 	echo '
 						</dl>
 						<div class="flow_auto">
+							<input type="submit" name="preview" value="', $txt['preview'] , '" class="button_submit">
 							<input type="submit" name="save" value="', $txt['rtm10'], '" style="margin-left: 1ex;" class="button_submit">
 							<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
 						</div>

+ 317 - 0
Themes/default/ReportedPosts.template.php

@@ -0,0 +1,317 @@
+<?php
+/**
+ * Simple Machines Forum (SMF)
+ *
+ * @package SMF
+ * @author Simple Machines http://www.simplemachines.org
+ * @copyright 2014 Simple Machines and individual contributors
+ * @license http://www.simplemachines.org/about/smf/license.php BSD
+ *
+ * @version 2.1 Alpha 1
+ */
+
+function template_reported_posts()
+{
+	global $context, $txt, $scripturl;
+
+	// Let them know the action was a success.
+	if (!empty($context['report_post_action']))
+	{
+		echo '
+			<div class="infobox">
+				', $txt['report_action_'. $context['report_post_action']], '
+			</div>';
+	}
+
+	echo '
+	<form id="reported_posts" action="', $scripturl, '?action=moderate;area=reports;sa=show', $context['view_closed'] ? ';closed' : '', ';start=', $context['start'], '" method="post" accept-charset="', $context['character_set'], '">
+		<div class="cat_bar">
+			<h3 class="catbg">
+				', $context['view_closed'] ? $txt['mc_reportedp_closed'] : $txt['mc_reportedp_active'], '
+			</h3>
+		</div>';
+
+	// Make the buttons.
+	$close_button = create_button('close.png', $context['view_closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', $context['view_closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', 'class="centericon"');
+	$details_button = create_button('details.png', 'mc_reportedp_details', 'mc_reportedp_details', 'class="centericon"');
+	$ignore_button = create_button('ignore.png', 'mc_reportedp_ignore', 'mc_reportedp_ignore', 'class="centericon"');
+	$unignore_button = create_button('ignore.png', 'mc_reportedp_unignore', 'mc_reportedp_unignore', 'class="centericon"');
+	$ban_button = create_button('close.png', 'mc_reportedp_ban', 'mc_reportedp_ban', 'class="centericon"');
+	$delete_button = create_button('delete.png', 'mc_reportedp_delete', 'mc_reportedp_delete', 'class="centericon"');
+
+	foreach ($context['reports'] as $report)
+	{
+		echo '
+		<div class="generic_list_wrapper ', $report['alternate'] ? 'windowbg' : 'windowbg2', '">
+			<div class="content">
+				<h5>
+					<strong>', !empty($report['topic']['board_name']) ? '<a href="' . $scripturl . '?board=' . $report['topic']['id_board'] . '.0">' . $report['topic']['board_name'] . '</a>' : '??', ' / <a href="', $report['topic']['href'], '">', $report['subject'], '</a></strong> ', $txt['mc_reportedp_by'], ' <strong>', $report['author']['link'], '</strong>
+				</h5>
+				<div class="smalltext">
+					', $txt['mc_reportedp_last_reported'], ': ', $report['last_updated'], '&nbsp;-&nbsp;';
+
+		// Prepare the comments...
+		$comments = array();
+		foreach ($report['comments'] as $comment)
+			$comments[$comment['member']['id']] = $comment['member']['link'];
+
+		echo '
+					', $txt['mc_reportedp_reported_by'], ': ', implode(', ', $comments), '
+				</div>
+				<hr>
+				', $report['body'], '
+				<br>
+				<ul class="quickbuttons">
+					<li><a href="', $report['report_href'], '">', $details_button, '</a></li>
+					<li><a href="', $scripturl, '?action=moderate;area=reports;sa=handle;ignore=', (int) !$report['ignore'], ';rid=', $report['id'], ';start=', $context['start'], ';', $context['session_var'], '=', $context['session_id'], ';', $context['mod-report-ignore_token_var'], '=', $context['mod-report-ignore_token'], '" class="report_ignore" data-ignore="', (int) !$report['ignore'], '">', $report['ignore'] ? $unignore_button : $ignore_button, '</a></li>
+					<li><a href="', $scripturl, '?action=moderate;area=reports;sa=handle;closed=', (int) !$report['closed'], ';rid=', $report['id'], ';start=', $context['start'], ';', $context['session_var'], '=', $context['session_id'], ';', $context['mod-report-closed_token_var'], '=', $context['mod-report-closed_token'], '">', $close_button, '</a></li>';
+
+		// Delete message button.
+		if (!$report['closed'] && (is_array($context['report_remove_any_boards']) && in_array($report['topic']['id_board'], $context['report_remove_any_boards'])))
+			echo '
+					<li><a href="', $scripturl, '?action=deletemsg;topic=', $report['topic']['id'] ,'.0;msg=', $report['topic']['id_msg'] ,';modcenter;', $context['session_var'], '=', $context['session_id'], '" class="delete_message">', $delete_button, '</a></li>';
+
+		// Ban this user button.
+		if (!$report['closed'] && !empty($context['report_manage_bans']))
+			echo '
+					<li><a href="', $scripturl, '?action=admin;area=ban;sa=add', (!empty($report['author']['id']) ? ';u='. $report['author']['id'] : ';msg='. $report['topic']['id_msg']) ,';', $context['session_var'], '=', $context['session_id'], '">', $ban_button, '</a></li>';
+
+		echo '
+					<li>', !$context['view_closed'] ? '<input type="checkbox" name="close[]" value="' . $report['id'] . '" class="input_check">' : '', '</li>
+				</ul>
+			</div>
+		</div>';
+	}
+
+	// Were none found?
+	if (empty($context['reports']))
+		echo '
+		<div class="windowbg2">
+			<div class="content">
+				<p class="centertext">', $txt['mc_reportedp_none_found'], '</p>
+			</div>
+		</div>';
+
+	echo '
+		<div class="pagesection">
+			', !empty($context['total_reports']) && $context['total_reports'] >= $context['reports_how_many'] ? '<div class="pagelinks floatleft">'. $context['page_index']. '</div>' : '' ,'
+			<div class="floatright">', !$context['view_closed'] ? '
+				<input type="hidden" name="'. $context['mod-report-close-all_token_var'] .'" value="'. $context['mod-report-close-all_token'] .'">
+				<input type="submit" name="close_selected" value="' . $txt['mc_reportedp_close_selected'] . '" class="button_submit">' : '', '
+			</div>
+		</div>
+		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
+	</form>';
+}
+
+
+// A block to show the current top reported posts.
+function template_reported_posts_block()
+{
+	global $context, $txt, $scripturl;
+
+	echo '
+		<div class="cat_bar">
+			<h3 class="catbg">
+				<span id="reported_posts_toggle" class="', !empty($context['admin_prefs']['mcrp']) ? 'toggle_down' : 'toggle_up', ' floatright" style="display: none;"></span>
+				<a href="', $scripturl, '?action=moderate;area=reports" id="reported_posts_link">', $txt['mc_recent_reports'], '</a>
+			</h3>
+		</div>
+		<div class="windowbg" id="reported_posts_panel">
+			<div class="content modbox">
+				<ul class="reset">';
+
+		foreach ($context['reported_posts'] as $report)
+			echo '
+					<li class="smalltext">
+						<a href="', $report['report_href'], '">', $report['subject'], '</a> ', $txt['mc_reportedp_by'], ' ', $report['author']['link'], '
+					</li>';
+
+		// Don't have any watched users right now?
+		if (empty($context['reported_posts']))
+			echo '
+					<li>
+						<strong class="smalltext">', $txt['mc_recent_reports_none'], '</strong>
+					</li>';
+
+		echo '
+				</ul>
+			</div>
+		</div>
+
+	<script><!-- // --><![CDATA[
+		var oReportedPostsPanelToggle = new smc_Toggle({
+			bToggleEnabled: true,
+			bCurrentlyCollapsed: ', !empty($context['admin_prefs']['mcrp']) ? 'true' : 'false', ',
+			aSwappableContainers: [
+				\'reported_posts_panel\'
+			],
+			aSwapImages: [
+				{
+					sId: \'reported_posts_toggle\',
+					altExpanded: ', JavaScriptEscape($txt['hide']), ',
+					altCollapsed: ', JavaScriptEscape($txt['show']), '
+				}
+			],
+			aSwapLinks: [
+				{
+					sId: \'reported_posts_link\',
+					msgExpanded: ', JavaScriptEscape($txt['mc_recent_reports']), ',
+					msgCollapsed: ', JavaScriptEscape($txt['mc_recent_reports']), '
+				}
+			],
+			oThemeOptions: {
+				bUseThemeSettings: true,
+				sOptionName: \'admin_preferences\',
+				sSessionVar: smf_session_var,
+				sSessionId: smf_session_id,
+				sThemeId: \'1\',
+				sAdditionalVars: \';admin_key=mcrp\'
+			}
+		});
+	// ]]></script>';
+}
+
+
+function template_viewmodreport()
+{
+	global $context, $scripturl, $txt;
+
+	// Let them know the action was a success.
+	if (!empty($context['report_post_action']))
+	{
+		echo '
+			<div class="infobox">
+				', $txt['report_action_'. $context['report_post_action']], '
+			</div>';
+	}
+
+	echo '
+	<div id="modcenter">
+		<form action="', $scripturl, '?action=moderate;area=reports;sa=handlecomment;rid=', $context['report']['id'], '" method="post" accept-charset="', $context['character_set'], '">
+			<div class="cat_bar">
+				<h3 class="catbg">
+					', sprintf($txt['mc_viewmodreport'], $context['report']['message_link'], $context['report']['author']['link']), '
+				</h3>
+			</div>
+			<div class="title_bar">
+				<h3 class="titlebg">
+					<span class="floatleft">
+						', sprintf($txt['mc_modreport_summary'], $context['report']['num_reports'], $context['report']['last_updated']), '
+					</span>
+					<span class="floatright">';
+
+		// Make the buttons.
+		$close_button = create_button('close.png', $context['report']['closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', $context['report']['closed'] ? 'mc_reportedp_open' : 'mc_reportedp_close', 'class="centericon"');
+		$ignore_button = create_button('ignore.png', 'mc_reportedp_ignore', 'mc_reportedp_ignore', 'class="centericon"');
+		$unignore_button = create_button('ignore.png', 'mc_reportedp_unignore', 'mc_reportedp_unignore', 'class="centericon"');
+
+		echo '
+						<a href="', $scripturl, '?action=moderate;area=reports;sa=handle;ignore=', (int) !$context['report']['ignore'], ';rid=', $context['report']['id'], ';', $context['session_var'], '=', $context['session_id'], ';', $context['mod-report-ignore_token_var'], '=', $context['mod-report-ignore_token'], '" class="report_ignore" data-ignore="', !$context['report']['ignore'] ,'">', $context['report']['ignore'] ? $unignore_button : $ignore_button, '</a>
+						<a href="', $scripturl, '?action=moderate;area=reports;sa=handle;closed=', (int) !$context['report']['closed'], ';rid=', $context['report']['id'], ';', $context['session_var'], '=', $context['session_id'], ';', $context['mod-report-closed_token_var'], '=', $context['mod-report-closed_token'], '">', $close_button, '</a>
+					</span>
+				</h3>
+			</div>
+			<div class="windowbg2">
+				<div class="content">
+					', $context['report']['body'], '
+				</div>
+			</div>
+			<br>
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['mc_modreport_whoreported_title'], '</h3>
+			</div>';
+
+	foreach ($context['report']['comments'] as $comment)
+		echo '
+			<div class="windowbg">
+				<div class="content">
+					<p class="smalltext">', sprintf($txt['mc_modreport_whoreported_data'], $comment['member']['link'] . (empty($comment['member']['id']) && !empty($comment['member']['ip']) ? ' (' . $comment['member']['ip'] . ')' : ''), $comment['time']), '</p>
+					<p>', $comment['message'], '</p>
+				</div>
+			</div>';
+
+	echo '
+			<br>
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['mc_modreport_mod_comments'], '</h3>
+			</div>
+				<div>';
+
+	if (empty($context['report']['mod_comments']))
+		echo '
+				<div class="information">
+					<p class="centertext">', $txt['mc_modreport_no_mod_comment'], '</p>
+				</div>';
+
+	foreach ($context['report']['mod_comments'] as $comment)
+	{
+		echo
+						'<div class="cat_bar">
+						<h4 class="catbg">', $comment['member']['link'], ':  <em class="smalltext">(', $comment['time'], ')</em>', ($comment['can_edit'] ? '<span class="floatright"><a href="' . $scripturl . '?action=moderate;area=reports;sa=editcomment;rid='. $context['report']['id'] .';mid='. $comment['id'] .';'. $context['session_var'] .'='. $context['session_id'] .'">'. $txt['mc_reportedp_comment_edit'] .'</a> | <a href="' . $scripturl . '?action=moderate;area=reports;sa=handlecomment;rid='. $context['report']['id'] .';mid='. $comment['id'] .';delete;'. $context['session_var'] .'='. $context['session_id']. ';'. $context['mod-reportC-delete_token_var'] .'='. $context['mod-reportC-delete_token'] .'" class="deleteModComment">'. $txt['mc_reportedp_comment_delete'] .'</a></span>' : '') ,'
+						</div></h4>';
+
+		echo '
+						<div class="windowbg">
+							<p class="content">', $comment['message'], '</p>
+						</div>';
+	}
+
+	echo '
+					<div class="title_bar">
+						<h3 class="titlebg">
+							<span class="floatleft">
+								', $txt['mc_reportedp_new_comment'], '
+							</span>
+						</h3>
+					</div>
+					<div class="content">
+						<textarea rows="2" cols="60" style="' . (isBrowser('is_ie8') ? 'width: 635px; max-width: 60%; min-width: 60%' : 'width: 60%') . ';" name="mod_comment"></textarea>
+						<div class="padding">
+							<input type="submit" name="add_comment" value="', $txt['mc_modreport_add_mod_comment'], '" class="button_submit">
+							<input type="hidden" name="', $context['mod-reportC-add_token_var'], '" value="', $context['mod-reportC-add_token'], '">
+						</div>
+					</div>
+				</div>
+			<br>';
+
+	template_show_list('moderation_actions_list');
+
+	echo '
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
+		</form>
+	</div>';
+}
+
+function template_edit_comment()
+{
+	global $context, $scripturl, $txt;
+
+	echo '
+	<div id="modcenter">
+		<form action="', $scripturl, '?action=moderate;area=reports;sa=editcomment;mid=', $context['comment_id'], ';rid=', $context['report_id'] ,';save" method="post" accept-charset="', $context['character_set'], '">';
+
+	echo '
+			<br>
+			<div class="cat_bar">
+				<h3 class="catbg">', $txt['mc_modreport_edit_mod_comment'] ,'</h3>
+			</div>
+			<div class="windowbg2">
+				<div class="content">';
+
+	echo '
+					<textarea rows="6" cols="60" style="' . (isBrowser('is_ie8') ? 'width: 635px; max-width: 60%; min-width: 60%' : 'width: 60%') . ';" name="mod_comment">', $context['comment']['body'] ,'</textarea>
+					<div>
+						<input type="submit" name="edit_comment" value="', $txt['mc_modreport_edit_mod_comment'], '" class="button_submit">
+					</div>
+				</div>
+			</div>
+			<br>';
+
+	echo '
+			<input type="hidden" name="', $context['mod-reportC-edit_token_var'], '" value="', $context['mod-reportC-edit_token'], '">
+			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
+		</form>
+	</div>';
+}
+?>

+ 13 - 2
Themes/default/languages/ModerationCenter.english.php

@@ -39,17 +39,20 @@ $txt['mc_reportedp_by'] = 'by';
 $txt['mc_reportedp_reported_by'] = 'Reported By';
 $txt['mc_reportedp_last_reported'] = 'Last Reported';
 $txt['mc_reportedp_none_found'] = 'No Reports Found';
-
+$txt['mc_reportedp_comment_none_found'] = 'No Moderator Comment Found';
+$txt['mc_reportedp_comment_edit'] = 'Edit';
+$txt['mc_reportedp_comment_delete'] = 'Delete';
 $txt['mc_reportedp_details'] = 'Details';
 $txt['mc_reportedp_close'] = 'Close';
 $txt['mc_reportedp_open'] = 'Open';
 $txt['mc_reportedp_ignore'] = 'Disregard';
 $txt['mc_reportedp_unignore'] = 'Undo Disregard';
 $txt['mc_reportedp_delete'] = 'Delete message';
+$txt['mc_reportedp_new_comment'] = 'Add a new comment';
 $txt['mc_reportedp_delete_confirm'] = 'Are you sure you wish to delete this message?';
 $txt['mc_reportedp_ban'] = 'Ban this user';
 // Do not use numeric entries in the below string.
-$txt['mc_reportedp_ignore_confirm'] = 'Are you sure you wish to ignore further reports about this message?\\n\\nThis will turn off further reports for all moderators of the forum.';
+$txt['mc_reportedp_ignore_confirm'] = 'Are you sure you wish to ignore further reports about this message? This will turn off further reports for all moderators of the forum.';
 $txt['mc_reportedp_close_selected'] = 'Close Selected';
 
 $txt['mc_groupr_group'] = 'Membergroups';
@@ -86,6 +89,7 @@ $txt['mc_modreport_modactions'] = 'Actions taken by other moderators';
 $txt['mc_modreport_mod_comments'] = 'Moderator Comments';
 $txt['mc_modreport_no_mod_comment'] = 'There are not currently any moderator comments';
 $txt['mc_modreport_add_mod_comment'] = 'Add Comment';
+$txt['mc_modreport_edit_mod_comment'] = 'Edit Comment';
 
 $txt['mc_viewmemberreport'] = 'Report for profile of %1$s';
 $txt['mc_memberreport_summary'] = 'There have been %1$d report(s) concerning this member.  The last report was %2$s.';
@@ -125,10 +129,17 @@ $txt['mc_warning_template_add'] = 'Add Template';
 $txt['mc_warning_template_modify'] = 'Edit Template';
 $txt['mc_warning_template_delete'] = 'Delete Selected';
 $txt['mc_warning_template_delete_confirm'] = 'Are you sure you want to delete the selected templates?';
+$txt['report_action_message_saved'] = 'You successfully created a new comment.';
+$txt['report_action_message_edited'] = 'You successfully edited the comment.';
 $txt['report_action_message_deleted'] = 'The message was successfully deleted.';
+$txt['report_action_message_edit_issue'] = 'The message you\'re trying to edit isn\'t available any more. Please check if it wasn\'t deleted already.';
+$txt['report_action_message_edit_cannot'] = 'I\'m sorry, you aren\'t allowed to edit this comment.';
+$txt['report_action_message_delete_cannot'] = 'I\'m sorry, you aren\'t allowed to delete this comment.';
+$txt['report_action_message_delete_issue'] = 'The message you\'re trying to delete isn\'t available any more. Please check if it wasn\'t deleted already.';
 $txt['report_action_ignore'] = 'The report was successfully ignored.';
 $txt['report_action_unignore'] = 'The report was successfully un-ignored.';
 $txt['report_action_close'] = 'The report was successfully closed.';
+$txt['report_action_close_all'] = 'You successfully closed all reports.';
 $txt['report_action_open'] = 'The report was successfully open.';
 $txt['report_action_close_all'] = 'You successfully closed all selected reports.';