b808121d68
This switches all if not most of the report feature code to using the new Java 8 date time API since it is much better for handling timezone's. This commit also creates a few new methods in UtilTime as they are used throughout the "report" and "chatsnap" packages. They may also come in useful for other developers using timezones.
542 lines
17 KiB
PHP
542 lines
17 KiB
PHP
<?php
|
|
|
|
require_once('snapshot.php');
|
|
require_once('report.php');
|
|
require_once('message.php');
|
|
require_once('user.php');
|
|
require_once('user_report.php');
|
|
|
|
const CATEGORIES = array(
|
|
0 => 'Global',
|
|
1 => 'Hacking',
|
|
2 => 'Chat Abuse'
|
|
);
|
|
|
|
const dataDir = 'data/';
|
|
const collapsedMessageCount = 20;
|
|
|
|
// In Java this is "DateTimeFormatter.ISO_LOCAL_DATE_TIME"
|
|
const jsonDateTimeFormat = 'Y-m-d\TH:i:s';
|
|
|
|
$dateTimeZone = new DateTimeZone('America/Chicago');
|
|
|
|
/** @var mysqli[] $connections */
|
|
$connections = array(); // String index = Connection name
|
|
|
|
/** @var User[] $users */ // Account id index
|
|
$users = array();
|
|
|
|
/** PARSE DB CONNECTIONS */
|
|
|
|
$dbConfigFile = new SplFileObject('database-config.dat');
|
|
|
|
if ($dbConfigFile->isFile())
|
|
{
|
|
while (!$dbConfigFile->eof())
|
|
{
|
|
$line = trim($dbConfigFile->fgets());
|
|
|
|
if ($line) // check not empty line
|
|
{
|
|
$parts = explode(' ', $line);
|
|
$fullUrl = $parts[1];
|
|
$urlParts = explode('/', $fullUrl);
|
|
$host = $urlParts[0];
|
|
$database = $urlParts[1];
|
|
|
|
$name = $parts[0];
|
|
$username = $parts[2];
|
|
$password = $parts[3];
|
|
|
|
$connection = new mysqli($host, $username, $password, $database);
|
|
|
|
if ($connection->connect_error) {
|
|
die("Connection \"$name\" failed: $connection->connect_error");
|
|
}
|
|
|
|
$connections[$name] = $connection;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
die('database-config.dat does not exist or is not a file.');
|
|
}
|
|
|
|
/**
|
|
* @param String $name
|
|
* @return mysqli
|
|
*/
|
|
function getConnection($name)
|
|
{
|
|
global $connections;
|
|
return $connections[$name];
|
|
}
|
|
|
|
/**
|
|
* @param Int $reportId
|
|
* @return Report
|
|
*/
|
|
function getReport($reportId)
|
|
{
|
|
$connection = getConnection("ACCOUNT");
|
|
$statement = $connection->prepare('SELECT * FROM reports
|
|
LEFT JOIN reportHandlers ON reports.id = reportHandlers.reportId
|
|
LEFT JOIN reportResults ON reports.id = reportResults.reportId
|
|
WHERE reports.id = ?');
|
|
|
|
try
|
|
{
|
|
$statement->bind_param('i', $reportId);
|
|
$statement->execute();
|
|
|
|
$result = $statement->get_result();
|
|
|
|
if ($row = $result->fetch_assoc())
|
|
{
|
|
$suspectUser = getUser($row['suspectId']);
|
|
$categoryId = $row['categoryId'];
|
|
$reportReasons = getReporters($reportId);
|
|
$handlerUser = null;
|
|
|
|
if (isset($row['handlerId']))
|
|
{
|
|
$handlerUser = getUser($row['handlerId']);
|
|
}
|
|
|
|
return new Report($reportId, $handlerUser, $suspectUser, $reportReasons, $categoryId);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
$statement->close();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function getSnapshot($reportId)
|
|
{
|
|
/** @var $messages Message[] */
|
|
$messages = array();
|
|
|
|
$connection = getConnection("ACCOUNT");
|
|
$statement = $connection->prepare("SELECT id, senderId, snapshotType, `server`, `time`, message FROM reportSnapshots, snapshots
|
|
WHERE snapshots.id = reportSnapshots.snapshotId
|
|
AND reportSnapshots.reportId = ?");
|
|
try
|
|
{
|
|
$statement->bind_param('i', $reportId);
|
|
$statement->execute();
|
|
$statement->bind_result($snapshotId, $senderId, $snapshotType, $server, $time, $message);
|
|
$statement->store_result();
|
|
|
|
while ($statement->fetch())
|
|
{
|
|
$recipients = getUsers(getSnapshotRecipients($snapshotId));
|
|
$message = new Message(getUser($senderId), $recipients, $time, $snapshotType, $message, $server);
|
|
array_push($messages, $message);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
$statement->close();
|
|
}
|
|
|
|
$snapshotUsers = array();
|
|
|
|
foreach ($messages as $message)
|
|
{
|
|
$sender = $message->getSender();
|
|
$snapshotUsers[$sender->getId()] = $sender;
|
|
|
|
foreach ($message->getRecipients() as $recipient)
|
|
{
|
|
$snapshotUsers[$recipient->getId()] = $recipient;
|
|
}
|
|
}
|
|
|
|
return new Snapshot($reportId, $messages, $snapshotUsers);
|
|
}
|
|
|
|
/**
|
|
* @param $snapshotId
|
|
* @return Integer[] array
|
|
*/
|
|
function getSnapshotRecipients($snapshotId)
|
|
{
|
|
$recipientIds = array();
|
|
$connection = getConnection("ACCOUNT");
|
|
$statement = $connection->prepare("SELECT recipientId FROM snapshotRecipients WHERE snapshotId = ?");
|
|
|
|
try
|
|
{
|
|
$statement->bind_param('i', $snapshotId);
|
|
$statement->execute();
|
|
$statement->bind_result($recipientId);
|
|
|
|
while ($statement->fetch())
|
|
{
|
|
array_push($recipientIds, $recipientId);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
$statement->close();
|
|
}
|
|
|
|
return $recipientIds;
|
|
}
|
|
|
|
/**
|
|
* @param Integer[] $ids
|
|
* @return User[] array
|
|
*/
|
|
function getUsers($ids)
|
|
{
|
|
$users = array();
|
|
|
|
foreach ($ids as $id)
|
|
{
|
|
array_push($users, getUser($id));
|
|
}
|
|
|
|
return $users;
|
|
}
|
|
|
|
/**
|
|
* @param $id
|
|
* @return User
|
|
*/
|
|
function getUser($id)
|
|
{
|
|
if (isset($users[$id]))
|
|
{
|
|
return $users[$id];
|
|
}
|
|
else
|
|
{
|
|
$connection = getConnection("ACCOUNT");
|
|
$statement = $connection->prepare('SELECT uuid, `name`, rank FROM accounts WHERE id = ?');
|
|
|
|
try
|
|
{
|
|
$statement->bind_param('i', $id);
|
|
$statement->execute();
|
|
$statement->bind_result($uuid, $name, $rank);
|
|
$statement->fetch();
|
|
|
|
$user = new User($id, $uuid, $name, $rank);
|
|
$users[$id] = $user;
|
|
|
|
return $user;
|
|
}
|
|
finally
|
|
{
|
|
$statement->close();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $reportId
|
|
* @return UserReport[]
|
|
*/
|
|
function getReporters($reportId)
|
|
{
|
|
global $dateTimeZone;
|
|
|
|
$connection = getConnection("ACCOUNT");
|
|
$statement = $connection->prepare("SELECT reporterId, `time`, reason FROM reportReasons WHERE reportId = ?");
|
|
$reportReasons = array();
|
|
|
|
try
|
|
{
|
|
$statement->bind_param('i', $reportId);
|
|
$statement->execute();
|
|
$statement->bind_result($reporterId, $time, $reason);
|
|
$statement->store_result(); // prevents issues with other queries running before this statement is closed
|
|
|
|
while ($statement->fetch())
|
|
{
|
|
$reportReasons[$reporterId] = new UserReport(getUser($reporterId), new DateTime($time, $dateTimeZone), $reason);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
$statement->close();
|
|
}
|
|
|
|
return $reportReasons;
|
|
}
|
|
|
|
/**
|
|
* @param Snapshot $snapshot
|
|
* @param Report $report
|
|
* @return User[]
|
|
*/
|
|
function getInvolvedUsers($snapshot, $report)
|
|
{
|
|
$involvedUsers = $snapshot->getPlayers();
|
|
$involvedUsers[$report->getSuspect()->getId()] = $report->getSuspect();
|
|
|
|
/** @var UserReport $reporter */
|
|
foreach ($report->getReporters() as $reporterReason) {
|
|
$reporter = $reporterReason->getUser();
|
|
$involvedUsers[$reporter->getId()] = $reporter;
|
|
}
|
|
|
|
return $involvedUsers;
|
|
}
|
|
|
|
/**
|
|
* @param Message $messageA
|
|
* @param Message $messageB
|
|
* @return int
|
|
*/
|
|
function compareMessageTimes($messageA, $messageB)
|
|
{
|
|
return $messageA->getTimestamp()->getTimestamp() - $messageB->getTimestamp()->getTimestamp();
|
|
}
|
|
|
|
/**
|
|
* @param String $dateTime
|
|
* @param DateTimeZone $timezone
|
|
* @return DateTime
|
|
*/
|
|
function parseDateTime($dateTime, $timezone)
|
|
{
|
|
return DateTime::createFromFormat(jsonDateTimeFormat, $dateTime, $timezone);
|
|
}
|
|
|
|
/**
|
|
* Converts an interval to minutes, days or months, depending on the size.
|
|
*
|
|
* @param DateInterval $interval
|
|
* @return string
|
|
*/
|
|
function approximateHumanInterval($interval)
|
|
{
|
|
if ($interval->y > 0)
|
|
{
|
|
$humanString = $interval->y . ' year' . ($interval->y != 0 ? 's' : '');
|
|
} else if ($interval->m > 0)
|
|
{
|
|
$humanString = $interval->m . ' month' . ($interval->m != 0 ? 's' : '');
|
|
}
|
|
else if ($interval->d > 0)
|
|
{
|
|
$humanString = $interval->d . ' day' . ($interval->d != 0 ? 's' : '');
|
|
}
|
|
else if ($interval->h > 0)
|
|
{
|
|
$humanString = $interval->h . ' hour' . ($interval->h != 0 ? 's' : '');
|
|
}
|
|
else
|
|
{
|
|
$humanString = $interval->i . ' minute' . ($interval->i != 0 ? 's' : '');
|
|
}
|
|
|
|
return $humanString;
|
|
}
|
|
|
|
function getExpandedURL()
|
|
{
|
|
$vars = $_GET;
|
|
$vars['expanded'] = true;
|
|
return '?' . http_build_query($vars);
|
|
}
|
|
|
|
$validId = isset($_GET['id']);
|
|
$idError = "";
|
|
|
|
$id = null;
|
|
$expanded = null;
|
|
$report = null;
|
|
$snapshot = null;
|
|
|
|
if ($validId)
|
|
{
|
|
$id = $_GET['id'];
|
|
$expanded = isset($_GET['expanded']) && $_GET['expanded'];
|
|
$report = getReport($id);
|
|
|
|
if ($report)
|
|
{
|
|
$snapshot = getSnapshot($id);
|
|
}
|
|
else
|
|
{
|
|
$validId = false;
|
|
$idError = "Invalid id.";
|
|
}
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<script src="js/jquery.js"></script>
|
|
<link rel="stylesheet" href="css/bootstrap.min.css">
|
|
<script src="js/bootstrap.min.js"></script>
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
|
|
<link rel="stylesheet" href="css/tiger.css">
|
|
<link href='https://fonts.googleapis.com/css?family=Crete+Round' rel='stylesheet' type='text/css'>
|
|
<link href='https://fonts.googleapis.com/css?family=Oswald' rel='stylesheet' type='text/css'>
|
|
<title>
|
|
<?php if ($validId): ?>
|
|
Report #<?= $report->getId() ?>
|
|
<?php else: ?>
|
|
Report System
|
|
<?php endif; ?>
|
|
|
|
· Mineplex
|
|
</title>
|
|
</head>
|
|
<body>
|
|
<div id="wrapper">
|
|
<div id="header">
|
|
<img src="img/logo.png" height="70px" width="70px" />
|
|
<h1>Report System</h1>
|
|
<!-- <h2><i class="fa fa-camera"></i> Chat Snap</h2> -->
|
|
</div>
|
|
<div id="search">
|
|
<form id="id-input" name="id-input" action="view.php" method="get">
|
|
<div class="input-group">
|
|
<input name="id" type="text" class="form-control" placeholder="Enter report id...">
|
|
<span class="input-group-btn">
|
|
<button class="btn btn-secondary" type="submit" form="id-input"><i class="fa fa-search"></i> Search</button>
|
|
</span>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<?php if (isset($_GET['id']) && !$validId && !empty($idError)): ?>
|
|
<div id="content" class="center-block" style="text-align: center; background-color: rgba(204, 34, 42, 0.52);">
|
|
<p class="error-oh-no" style="font-size: 60px;">What did you do?!?!?</p>
|
|
<img src="img/shaun.gif" />
|
|
<p class="error-oh-no" style="font-size: 40px;">Error: <?= $idError ?></p>
|
|
<br>
|
|
</div>
|
|
<?php else: ?>
|
|
<?php if (!isset($_GET['id'])) exit(); ?>
|
|
|
|
<div id="content">
|
|
<div>
|
|
<hr>
|
|
<h2 style="font-family: 'Oswald', sans-serif; text-align: center;">
|
|
Report #<?= $report->getId() ?>
|
|
</h2>
|
|
<hr>
|
|
</div>
|
|
<div class="row">
|
|
<div id="chat" class="col-lg-7">
|
|
<h4><i class="fa fa-comments"></i> Chat Log</h4>
|
|
<hr>
|
|
<div id="log" class="text-muted ">
|
|
<?php
|
|
|
|
// INITIALIZE
|
|
|
|
// Get messages and the amount that we are going to display
|
|
$messages = $snapshot->getMessages();
|
|
$messageCount = count($messages);
|
|
$displayAmount = $expanded || $messageCount <= collapsedMessageCount ? $messageCount : collapsedMessageCount;
|
|
|
|
// Put all reporter usernames in array for easy access later
|
|
$reporterUsernames = array();
|
|
foreach ($report->getReporters() as $reporterReason)
|
|
{
|
|
$reporterUsernames[count($reporterUsernames)] = $reporterReason->getUser()->getUsername();
|
|
}
|
|
|
|
$involvedUsers = getInvolvedUsers($snapshot, $report);
|
|
|
|
$reportCreationTime = $report->getTimeCreated();
|
|
$age = approximateHumanInterval($reportCreationTime->diff(new DateTime('now', $reportCreationTime->getTimezone())));
|
|
|
|
if ($displayAmount == 0): ?>
|
|
<span class="black">No chat log available for this report.</span>
|
|
<?php else:
|
|
for ($i = 0; $i < $displayAmount; $i++):
|
|
$message = $messages[$i];
|
|
$typeId = $message->getType();
|
|
$typeDisplayName = Message::$TYPE_DISPLAY_NAMES[$typeId];
|
|
$isPM = $typeId == Message::TYPE_PM;
|
|
|
|
// If this is a PM, then the "-> <recipient>" suffix will be applied.
|
|
$involved = $message->getSender()->getUsername() . ($isPM ? " -> " . $message->getRecipients()[0]->getUsername() : "");
|
|
?>
|
|
|
|
<span class="label <?= $isPM ? "label-primary chat pm" : "label-info chat" ?>" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;"><?= $typeDisplayName ?></span>
|
|
<span class="black"><?= $involved; ?>:</span> <?= $message->getMessage(); ?>
|
|
|
|
<?php if ($i < $displayAmount - 1): // Don't break on the last element ?>
|
|
<br />
|
|
<?php endif; ?>
|
|
<?php endfor; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if (!$expanded && $displayAmount < $messageCount): ?>
|
|
<br />
|
|
<a href="<?= getExpandedURL() ?>">Show All (<?= $messageCount ?> messages)</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div id="users" class="col-lg-5">
|
|
<h4><i class="fa fa-info-circle"></i> Information</h4>
|
|
<hr>
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<i class="fa fa-clock-o fa-fw"></i>
|
|
<span class="label label-pill label-default" title="Last Report: <?= $reportCreationTime->format('Y/m/d H:i:s T') ?>"><?= $age . ' ago' ?></span>
|
|
<br>
|
|
|
|
<i class="fa fa-user-plus fa-fw"></i>
|
|
<span class="label label-pill label-success">Reported by <?= implode(", ", $reporterUsernames) ?></span>
|
|
<br>
|
|
|
|
<i class="fa fa-user-times fa-fw"></i>
|
|
<span class="label label-pill label-danger">Suspect is <?= $report->getSuspect()->getUsername() ?></span>
|
|
<br>
|
|
|
|
<i class="fa fa-gavel fa-fw"></i>
|
|
<span class="label label-pill label-warning">
|
|
<?php if ($report->getHandler() != null): ?>
|
|
Staff Member assigned is <?= $report->getHandler()->getUsername() ?>
|
|
<?php else: ?>
|
|
No Staff Member assigned
|
|
<?php endif; ?>
|
|
</span>
|
|
<br>
|
|
</div>
|
|
</div>
|
|
<br>
|
|
|
|
<h4><i class="fa fa-users"></i> Users</h4>
|
|
<hr>
|
|
<?php foreach($involvedUsers as $user): ?>
|
|
<img src="http://cravatar.eu/avatar/<?= $user->getUUID() ?>/55.png" class="pull-left" />
|
|
<b class="name"><?= $user->getUsername() ?></b> <span class="label label-staff name"><?= ucwords(strtolower($user->getRank())) ?></span><br> <!-- TODO different styling for different ranks -->
|
|
<code style="font-size: 11px;"><?= $user->getUUID() ?></code>
|
|
<br><br>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div id="footer">
|
|
<a href="http://www.mineplex.com"><img src="img/logo-full.png" width="225px" /></a>
|
|
<div class="btn-group pull-right indent-link" style="font-family: 'Crete Round', serif; padding-top: 10px;">
|
|
<a href="http://www.mineplex.com" class="btn btn-link btn-small text-muted">Home</a>
|
|
<a href="http://www.mineplex.com/shop/" class="btn btn-link btn-small text-muted">Shop</a>
|
|
<a href="http://www.mineplex.com/forums/" class="btn btn-link btn-small text-muted">Forums</a>
|
|
<a href="http://www.mineplex.com/supporthub/" class="btn btn-link btn-small text-muted">Support</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
<?php foreach ($connections as $connection) {
|
|
$connection->close();
|
|
} ?>
|