svrjs-mods-directory/includes/page_reviews.php
2024-12-27 15:05:54 +01:00

319 lines
No EOL
14 KiB
PHP

<?php
if (!defined('SVRJS_MOD_DIRECTORY')) die;
$errorMessage = null;
$reviewSubmitted = false;
$reviewDeleted = false;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (!isset($_POST['_csrf']) || $_POST['_csrf'] != $_SESSION['csrf']) {
$errorMessage = "Potential CSRF attack detected.";
} elseif (!isset($_POST['action'])) {
$errorMessage = "No action specified.";
} elseif ($_POST['action'] == "submit") {
if (!isset($_POST['rating'], $_POST['review']) || !$_POST['rating'] || !$_POST['review']) {
$errorMessage = "You need to input rating and review.";
} elseif (!filter_var($_POST['rating'], FILTER_VALIDATE_INT)) {
$errorMessage = "Invalid rating.";
} else {
$rating = intval($_POST['rating']);
if ($rating < 1 || $rating > 5) {
$errorMessage = "Invalid rating.";
} else {
$statement = $connection->prepare("REPLACE INTO reviews (
`mod`,
user,
rating,
review
) VALUES (
?,
?,
?,
?
);");
if (!$statement) {
$errorMessage = "An unexpected error occurred while submitting the review.";
} else {
$statement->bind_param('iiis', $modData['id'], $_SESSION['user'], $rating, $_POST['review']);
if (!$statement->execute()) {
$errorMessage = "An unexpected error occurred while submitting the review.";
} else {
$reviewSubmitted = true;
}
}
}
}
} elseif ($_POST['action'] == "delete") {
$statement = $connection->prepare("DELETE FROM reviews WHERE `mod` = ? AND user = ?");
if (!$statement) {
$errorMessage = "An unexpected error occurred while deleting the review.";
} else {
$statement->bind_param('ii', $modData['id'], $_SESSION['user']);
if (!$statement->execute()) {
$errorMessage = "An unexpected error occurred while deleting the review.";
} else {
$reviewDeleted = true;
}
}
} else {
$errorMessage = "Unknown action specified.";
}
}
if ($reviewSubmitted) {
$pageTitle = "Review submitted";
$pageDescription = "Your review has been submitted.";
} elseif ($reviewDeleted) {
$pageTitle = "Review deleted";
$pageDescription = "Your review has been deleted.";
} else {
$pageTitle = 'Reviews for "' . $modData['name'] . '" mod';
$pageDescription = 'See reviews for the "' . $modData['name'] . '" mod on SVR.JS Mods directory.';
$pageImage = (isset($modData['image_ext']) && $modData['image_ext'] ? 'mods/' . urlencode(str_replace(['/', '\\'], '', $modData['slug'])) . '.' . urlencode(str_replace(['/', '\\'], '', $modData['image_ext'])) : 'mod-missing.png');
}
include 'header.php';
?>
<main class="content">
<?php if ($reviewSubmitted) { ?>
<h1>Review submitted</h1>
<p>Your review has been submitted.</p>
<p><a href="<?php echo htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'reviews/' . urlencode($modData['slug'])); ?>" class="btn">Return to mod reviews</a></p>
<?php } elseif ($reviewDeleted) { ?>
<h1>Review deleted</h1>
<p>Your review has been deleted.</p>
<p><a href="<?php echo htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'reviews/' . urlencode($modData['slug'])); ?>" class="btn">Return to mod reviews</a></p>
<?php } else { ?>
<h1>Reviews for &ldquo;<?php echo htmlspecialchars($modData['name']) ?>&rdquo; mod</h1>
<p><a href="<?php echo htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'mod/' . urlencode($modData['slug'])); ?>">Return to the mod page</a></p>
<?php if ($errorMessage) echo '<p class="form-error">' . htmlspecialchars($errorMessage) . '</p>'; ?>
<?php
if ($modData['rating']) {
$stars = round($modData['rating']);
echo '<p class="rating">';
echo '<span class="rating-rating">' . htmlspecialchars(number_format($modData['rating'], 2)) . '</span>';
echo '<span class="rating-stars">';
for ($i = 0; $i < $stars; $i++) {
echo '<span class="rating-star rating-star-higlighted">&starf;</span>';
}
for ($i = $stars; $i < 5; $i++) {
echo '<span class="rating-star">&starf;</span>';
}
echo '</span></p>';
}
?>
<p><strong>Reviews</strong>: <?php echo htmlspecialchars(number_format($modData['reviews'], 0)); ?></p>
<h2>Submit a review</h2>
<?php if (!isset($_SESSION['user'])) { ?>
<p>You need to be logged in to submit a review on this mod.</p>
<?php } elseif ($_SESSION['user'] == $modData['user_id']) { ?>
<p>As a mod publisher, you cannot submit a review on this mod.</p>
<?php } else { ?>
<?php
$userReview = null;
$statement = $connection->prepare('SELECT rating, review FROM reviews WHERE `mod` = ? AND user = ?;');
if ($statement) {
$statement->bind_param('ii', $modData['id'], $_SESSION['user']);
$statement->execute();
$result = $statement->get_result();
if ($result) {
$userReview = $result->fetch_assoc();
}
$statement->close();
}
?>
<form action="<?php echo htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'reviews/' . urlencode($modData['slug'])) ?>" method="post" class="form">
<div class="form-block-checkbox">
<span>Rating:</span>
<span class="rating-select">
<input type="radio" name="rating" id="rate-5" value="5" required <?php echo $userReview && $userReview['rating'] == 5 ? 'checked' : ''; ?>>
<label for="rate-5" title="5 stars">&starf;</label>
<input type="radio" name="rating" id="rate-4" value="4" required <?php echo $userReview && $userReview['rating'] == 4 ? 'checked' : ''; ?>>
<label for="rate-4" title="4 stars">&starf;</label>
<input type="radio" name="rating" id="rate-3" value="3" required <?php echo $userReview && $userReview['rating'] == 3 ? 'checked' : ''; ?>>
<label for="rate-3" title="3 stars">&starf;</label>
<input type="radio" name="rating" id="rate-2" value="2" required <?php echo $userReview && $userReview['rating'] == 2 ? 'checked' : ''; ?>>
<label for="rate-2" title="2 stars">&starf;</label>
<input type="radio" name="rating" id="rate-1" value="1" required <?php echo $userReview && $userReview['rating'] == 1 ? 'checked' : ''; ?>>
<label for="rate-1" title="1 star">&starf;</label>
</span>
</div>
<div class="form-block">
<label for="review">Review:</label>
<textarea name="review" id="review" maxlength="1000" required><?php echo $userReview && $userReview['review'] ? htmlspecialchars($userReview['review']) : ''; ?></textarea>
</div>
<div class="form-block">
<input type="submit" value="<?php echo $userReview ? 'Edit review' : 'Submit review' ?>">
</div>
<input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($_SESSION['csrf']) ?>">
<input type="hidden" name="action" value="submit">
</form>
<?php if ($userReview) { ?>
<h2>Delete your review</h2>
<form action="<?php echo htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'reviews/' . urlencode($modData['slug'])) ?>" method="post" class="form">
<div class="form-block">
<input type="submit" value="Delete review">
</div>
<input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($_SESSION['csrf']) ?>">
<input type="hidden" name="action" value="delete">
</form>
<?php } ?>
<?php } ?>
<h2>Reviews</h2>
<?php
$countStatement = $connection->prepare('SELECT COUNT(reviews.id) AS count
FROM reviews
JOIN (
SELECT mods.id AS id, mods.is_removed AS is_removed, mods.name AS name, mods.slug AS slug FROM mods
JOIN users ON users.id = mods.user AND users.is_verified = 1 AND users.is_deleted = 0 AND users.is_suspended = 0
) AS mods ON mods.id = reviews.mod
JOIN users ON users.id = reviews.user
WHERE mods.id = ?
AND mods.is_removed = 0
AND users.is_suspended = 0
AND users.is_deleted = 0
AND users.is_verified = 1;');
if (!$countStatement) {
echo "<p>An unexpected error occurred while fetching reviews.</p>";
} else {
$countStatement->bind_param('i', $modData['id']);
$countStatement->execute();
$countResult = $countStatement->get_result();
if (!$countResult) {
echo "<p>An unexpected error occurred while fetching reviews.</p>";
$countStatement->close();
} else {
$countRow = $countResult->fetch_assoc();
$countStatement->close();
if (!$countRow) {
echo "<p>An unexpected error occurred while fetching reviews.</p>";
} else {
$modCount = $countRow['count'];
$totalPages = ceil($modCount / PAGE_MODS);
$statement = $connection->prepare('SELECT
reviews.id AS id,
reviews.rating AS rating,
reviews.review AS review,
mods.name AS mod_name,
mods.slug AS mod_slug,
users.username AS user,
users.id AS user_id
FROM reviews
JOIN (
SELECT mods.id AS id, mods.is_removed AS is_removed, mods.name AS name, mods.slug AS slug FROM mods
JOIN users ON users.id = mods.user AND users.is_verified = 1 AND users.is_deleted = 0 AND users.is_suspended = 0
) AS mods ON mods.id = reviews.mod
JOIN users ON users.id = reviews.user
WHERE mods.id = ?
AND mods.is_removed = 0
AND users.is_suspended = 0
AND users.is_deleted = 0
AND users.is_verified = 1
ORDER BY reviews.id DESC
LIMIT ?,?;');
if (!$statement) {
echo "<p>An unexpected error occurred while fetching reviews.</p>";
} else {
$pageNumber = isset($_GET['page']) && filter_var($_GET['page'], FILTER_VALIDATE_INT) ? intval($_GET['page']) : 1;
$firstNumber = PAGE_REVIEWS * ($pageNumber - 1);
$pageReviews = PAGE_REVIEWS;
$statement->bind_param('iii', $modData['id'], $firstNumber, $pageReviews);
$statement->execute();
$result = $statement->get_result();
if (!$result) {
echo "<p>An unexpected error occurred while fetching reviews.</p>";
$statement->close();
} else {
$reviewsPresent = false;
while ($review = $result->fetch_assoc()) {
$reviewsPresent = true;
echo '<div class="review"><div class="review-header">';
$stars = round($review['rating']);
echo '<span class="rating-stars">';
for ($i = 0; $i < $stars; $i++) {
echo '<span class="rating-star rating-star-higlighted">&starf;</span>';
}
for ($i = $stars; $i < 5; $i++) {
echo '<span class="rating-star">&starf;</span>';
}
echo ' | by <a href="' . htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'user/' . urlencode($review['user'])) . '">' . htmlspecialchars($review['user']) . '</a> | on <a href="' . htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'mod/' . urlencode($review['mod_slug'])) . '">' . htmlspecialchars($review['mod_name']) . '</a></div><p>' . str_replace(["\r\n", "\n", "\r"], '<br/>', htmlspecialchars($review['review'])) . '</div>';
}
if (!$reviewsPresent) {
echo '<p>No reviews.</p>';
}
$statement->close();
if ($totalPages > 1) {
$begPage = $pageNumber - 2;
$endPage = $pageNumber + 2;
if ($endPage > $totalPages) {
$begPage -= $endPage - $totalPages;
$endPage = $totalPages;
}
if ($begPage < 1) {
$endPage += 1 - $begPage;
$begPage = 1;
}
echo '<div class="pagination">';
echo $pageNumber <= 1 ? '<span>&lsaquo;</span>' : '<a href="' . htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'reviews/' . urlencode($modData['slug']) . '?page=' . urlencode(strval($pageNumber - 1))) . '">&lsaquo;</a>';
for ($i = 0; $i < ($totalPages > 5 ? 5 : $totalPages); $i++) {
echo $pageNumber == $begPage + $i ? '<span>' . htmlspecialchars(strval($begPage + $i)) . '</span>' : '<a href="' . htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'reviews/' . urlencode($modData['slug']) . '?page=' . urlencode(strval($begPage + $i))) . '">' . htmlspecialchars(strval($begPage + $i)) . '</a>';
}
echo $pageNumber >= $totalPages ? '<span>&rsaquo;</span>' : '<a href="' . htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'reviews/' . urlencode($modData['slug']) . '?page=' . urlencode(strval($pageNumber + 1))) . '">&rsaquo;</a>';
echo '</div>';
}
}
}
}
}
}
?>
<?php } ?>
</main>
<?php
include 'footer.php';
if ($reviewSubmitted) {
$username = null;
if (isset($_SESSION['user'])) {
$usernameStatement = $connection->prepare('SELECT username FROM users WHERE id = ?;');
if ($usernameStatement) {
$usernameStatement->bind_param('i', $_SESSION['user']);
$usernameStatement->execute();
$usernameResult = $usernameStatement->get_result();
if ($usernameResult) {
$usernameRow = $usernameResult->fetch_assoc();
if ($usernameRow) {
$username = $usernameRow['username'];
}
}
$usernameStatement->close();
}
}
sendEmail(
[[
"name" => $modData['user'],
"address" => $modData['user_email']
]],
($username ? $username : 'Someone') . ' has left a review on your mod',
($username ? $username : 'Someone') . " has left you a " . intval($_POST['rating']) . "-star review on your \"" . $modData['name'] . "\" mod. The contents of the review are below:\n\n" . $_POST['review']
);
}
?>