mirror of
https://github.com/OPSnet/Gazelle.git
synced 2026-01-17 03:04:47 -05:00
260 lines
9.7 KiB
PHP
260 lines
9.7 KiB
PHP
<?php
|
||
/** @phpstan-var \Gazelle\User $Viewer */
|
||
/** @phpstan-var \Gazelle\Cache $Cache */
|
||
/** @phpstan-var \Twig\Environment $Twig */
|
||
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
|
||
// phpcs:disable Generic.WhiteSpace.ScopeIndent.Incorrect
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace Gazelle;
|
||
|
||
use Gazelle\Enum\CacheBucket;
|
||
|
||
$forumMan = new Manager\Forum();
|
||
if (isset($_GET['postid'])) {
|
||
$post = new Manager\ForumPost()->findById((int)$_GET['postid']);
|
||
if (is_null($post)) {
|
||
Error404::error();
|
||
}
|
||
if (!isset($_GET['threadid'])) {
|
||
header("Location: {$post->location()}");
|
||
exit;
|
||
}
|
||
$thread = $post->thread();
|
||
} elseif (isset($_GET['threadid'])) {
|
||
$post = null;
|
||
$thread = new Manager\ForumThread()->findById((int)$_GET['threadid']);
|
||
if (is_null($thread)) {
|
||
Error404::error();
|
||
}
|
||
} else {
|
||
Error404::error();
|
||
}
|
||
$forum = $thread->forum();
|
||
|
||
if (!$Viewer->readAccess($forum)) {
|
||
Error403::error();
|
||
}
|
||
|
||
//Escape strings for later display
|
||
$ForumName = display_str($forum->name());
|
||
$IsDonorForum = ($forum->id == DONOR_FORUM);
|
||
$PerPage = $Viewer->postsPerPage();
|
||
|
||
//Post links utilize the catalogue & key params to prevent issues with custom posts per page
|
||
$PostNum = match (true) {
|
||
isset($_GET['post']) => (int)$_GET['post'],
|
||
$post && !$post->isPinned() => $post->priorPostTotal(),
|
||
default => 1,
|
||
};
|
||
|
||
$Page = max(1, (int)($_GET['page'] ?? (int)ceil(min($thread->postTotal(), $PostNum) / $PerPage)));
|
||
if (($Page - 1) * $PerPage > $thread->postTotal()) {
|
||
$Page = (int)ceil($thread->postTotal() / $PerPage);
|
||
}
|
||
$slice = $thread->slice(perPage: $PerPage, page: $Page);
|
||
$paginator = new Util\Paginator($PerPage, $Page);
|
||
$paginator->setTotal($thread->postTotal());
|
||
|
||
$firstOnPage = current($slice)['ID'] ?? 0;
|
||
$lastOnPage = count($slice) ? end($slice)['ID'] : 0;
|
||
if ($lastOnPage <= $thread->pinnedPostId() && $thread->postTotal() <= $PerPage * $Page) {
|
||
$lastOnPage = $thread->pinnedPostId();
|
||
}
|
||
|
||
$quote = new User\Quote($Viewer);
|
||
if ($quote->unreadTotal()) {
|
||
$quote->clearThread($thread, $firstOnPage, $lastOnPage);
|
||
}
|
||
|
||
$lastRead = $thread->userLastReadPost($Viewer);
|
||
if ($lastRead < $lastOnPage) {
|
||
$thread->catchup($Viewer, $lastOnPage);
|
||
}
|
||
|
||
$isSubscribed = new User\Subscription($Viewer)->isSubscribed($thread);
|
||
if ($isSubscribed) {
|
||
$Cache->delete_value('subscriptions_user_new_' . $Viewer->id);
|
||
}
|
||
|
||
$userMan = new Manager\User();
|
||
$avatarFilter = Util\Twig::factory($userMan)->createTemplate('{{ user|avatar(viewer)|raw }}');
|
||
|
||
$transitions = new Manager\ForumTransition()->threadTransitionList($Viewer, $thread);
|
||
$department = $forum->departmentList($Viewer);
|
||
$auth = $Viewer->auth();
|
||
|
||
View::show_header("Forums › $ForumName › {$thread->title()}",
|
||
['js' => 'comments,subscriptions,bbcode' . ($IsDonorForum ? ',donor_titles' : '')]
|
||
);
|
||
echo $Twig->render('forum/thread-header.twig', [
|
||
'is_subbed' => $isSubscribed,
|
||
'paginator' => $paginator,
|
||
'thread' => $thread,
|
||
'transition_list' => $transitions,
|
||
'viewer' => $Viewer,
|
||
]);
|
||
|
||
echo $Twig->render('forum/poll.twig', [
|
||
'poll' => $thread->hasPoll() ? new ForumPoll($thread) : false,
|
||
'user_man' => $userMan,
|
||
'viewer' => $Viewer,
|
||
]);
|
||
|
||
// Squeeze in stickypost
|
||
if ($thread->pinnedPostId()) {
|
||
if (!$slice) {
|
||
$slice = [$thread->pinnedPostInfo()];
|
||
} else {
|
||
if ($thread->pinnedPostId() != current($slice)['ID']) {
|
||
array_unshift($slice, $thread->pinnedPostInfo());
|
||
}
|
||
if ($thread->pinnedPostId() != $slice[count($slice) - 1]['ID']) {
|
||
$slice[] = $thread->pinnedPostInfo();
|
||
}
|
||
}
|
||
}
|
||
|
||
// Enable TOC
|
||
\Text::$TOC = true;
|
||
|
||
foreach ($slice as $Key => $Post) {
|
||
[$PostID, $AuthorID, $AddedTime, $Body, $EditedUserID, $EditedTime] = array_values($Post);
|
||
$author = new User($AuthorID);
|
||
$tableClass = ['forum_post', 'wrap_overflow', 'box vertical_margin'];
|
||
if (
|
||
(!$thread->isLocked() || $thread->isPinned())
|
||
&& $PostID > $lastRead
|
||
&& strtotime($AddedTime) > $Viewer->forumCatchupEpoch()
|
||
) {
|
||
$tableClass[] = 'forum_unread';
|
||
}
|
||
if (!$Viewer->showAvatars()) {
|
||
$tableClass[] = 'noavatar';
|
||
}
|
||
if ($AuthorID == $thread->authorId()) {
|
||
$tableClass[] = 'important_user';
|
||
}
|
||
if ($PostID == $thread->pinnedPostId()) {
|
||
$tableClass[] = 'sticky_post';
|
||
}
|
||
?>
|
||
<table class="<?= implode(' ', $tableClass) ?>" id="post<?= $PostID ?>">
|
||
<colgroup>
|
||
<?php if ($Viewer->showAvatars()) { ?>
|
||
<col class="col_avatar" />
|
||
<?php } ?>
|
||
<col class="col_post_body" />
|
||
</colgroup>
|
||
<tr class="colhead_dark">
|
||
<td class="forum-post-head" colspan="<?= $Viewer->showAvatars() ? 2 : 1 ?>">
|
||
<span style="float: left;"><a class="post_id" href="forums.php?action=viewthread&threadid=<?=$thread->id ?>&postid=<?=$PostID?>#post<?=$PostID?>">#<?=$PostID?></a>
|
||
<?= $userMan->displayUsername($AuthorID, $Viewer, showFull: true, isDonorForum: $IsDonorForum) ?>
|
||
<?php
|
||
$userTitle = $author->title();
|
||
if (!empty($userTitle)) {
|
||
?> <span class="user_title">(<?= $userTitle ?>)</span><?php
|
||
}
|
||
?>
|
||
<?=time_diff($AddedTime, 2); ?>
|
||
<span id="postcontrol-<?= $PostID ?>">
|
||
<?php if (!$thread->isLocked() && !$Viewer->disablePosting()) { ?>
|
||
- <a href="#quickpost" class="brackets quotable" id="quote_<?=$PostID?>" data-id="<?=$PostID?>" data-author="<?= $author->username() ?>" title="Select text to quote">Quote</a>
|
||
<?php
|
||
}
|
||
if ((!$thread->isLocked() && $Viewer->writeAccess($forum) && $AuthorID == $Viewer->id) && !$Viewer->disablePosting() || $Viewer->permitted('site_moderate_forums')) {
|
||
?>
|
||
- <a href="#post<?= $PostID ?>" id="edit-<?= $PostID ?>" data-author="<?= $AuthorID ?>" data-key="<?= $Key ?>" class="edit-post brackets">Edit</a>
|
||
<?php } ?>
|
||
<?php if ($Viewer->permitted('site_forum_post_delete') && $thread->postTotal() > 1) { ?>
|
||
- <a href="#" data-id="<?= $PostID ?>" class="brackets delete-post">Delete</a>
|
||
<?php
|
||
}
|
||
if ($PostID == $thread->pinnedPostId()) { ?>
|
||
<strong><span class="sticky_post_label" class="brackets">Pinned</span></strong>
|
||
<?php if ($Viewer->permitted('site_moderate_forums')) { ?>
|
||
- <a href="forums.php?action=sticky_post&threadid=<?=$thread->id ?>&postid=<?=$PostID?>&remove=true&auth=<?=$auth?>" title="Unpin this post" class="brackets tooltip">X</a>
|
||
<?php
|
||
}
|
||
} else {
|
||
if ($Viewer->permitted('site_moderate_forums')) {
|
||
?>
|
||
- <a href="forums.php?action=sticky_post&threadid=<?=$thread->id ?>&postid=<?=$PostID?>&auth=<?=$auth?>" title="Pin this post" class="tooltip" style="font-size: 1.4em">📌</a>
|
||
<?php
|
||
}
|
||
}
|
||
?>
|
||
</span>
|
||
</span>
|
||
<span id="bar<?=$PostID?>" style="float: right">
|
||
<a href="reports.php?action=report&type=post&id=<?=$PostID?>" class="brackets">Report</a>
|
||
<?php
|
||
$author = new User($AuthorID);
|
||
if ($Viewer->permitted('users_warn') && $Viewer->id != $AuthorID && $Viewer->classLevel() >= $author->classLevel()) {
|
||
?>
|
||
<form class="manage_form hidden" name="user" id="warn<?=$PostID?>" action="" method="post">
|
||
<input type="hidden" name="action" value="warn" />
|
||
<input type="hidden" name="auth" value="<?= $auth ?>" />
|
||
<input type="hidden" name="postid" value="<?=$PostID?>" />
|
||
<input type="hidden" name="userid" value="<?=$AuthorID?>" />
|
||
<input type="hidden" name="key" value="<?=$Key?>" />
|
||
</form>
|
||
- <a href="#" onclick="$('#warn<?=$PostID?>').raw().submit(); return false;" class="brackets">Warn</a>
|
||
<?php } ?>
|
||
|
||
<a href="#">↑</a>
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<?php if ($Viewer->showAvatars()) { ?>
|
||
<td class="avatar" valign="top">
|
||
<?= $avatarFilter->render(['user' => $author, 'viewer' => $Viewer]) ?>
|
||
</td>
|
||
<?php } ?>
|
||
<td class="body" valign="top"<?php if (!$Viewer->showAvatars()) {
|
||
echo ' colspan="2"'; } ?>>
|
||
<div id="content<?=$PostID?>">
|
||
<?= \Text::full_format($Body, cache: IMAGE_CACHE_ENABLED, bucket: CacheBucket::forum) ?>
|
||
<?php if ($EditedUserID) { ?>
|
||
<br />
|
||
<br />
|
||
<span class="last_edited">
|
||
<?php if ($Viewer->permitted('site_admin_forums')) { ?>
|
||
<a href="#content<?=$PostID?>" onclick="LoadEdit('forums', <?=$PostID?>, 1); return false;">«</a>
|
||
<?php } ?>
|
||
Last edited by
|
||
<?= $userMan->displayUsername($EditedUserID, $Viewer, isDonorForum: $IsDonorForum) ?> <?=time_diff($EditedTime, 2)?>
|
||
</span>
|
||
<?php } ?>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<?php } ?>
|
||
<div class="breadcrumbs">
|
||
<a href="forums.php">Forums</a> › <?= $forum->link() ?> › <?= display_str($thread->title()) ?>
|
||
</div>
|
||
<?php
|
||
echo $paginator->linkbox();
|
||
|
||
if ($Viewer->permitted('site_moderate_forums') || ($Viewer->writeAccess($forum) && !$thread->isLocked())) {
|
||
$lastPost = end($slice);
|
||
echo $Twig->render('reply.twig', [
|
||
'object' => $thread,
|
||
'merge' => strtotime($lastPost['AddedTime']) > time() - 3600 && $lastPost['AuthorID'] == $Viewer->id,
|
||
'subbed' => $isSubscribed,
|
||
'textarea' => new Util\Textarea('quickpost', '', 90, 8)->setPreviewManual(true),
|
||
'viewer' => $Viewer,
|
||
]);
|
||
}
|
||
|
||
echo $Twig->render('forum/thread-footer.twig', [
|
||
'forum_list' => $forumMan->forumList(),
|
||
'page' => $Page,
|
||
'thread' => $thread,
|
||
'transition_list' => $transitions,
|
||
'viewer' => $Viewer,
|
||
]);
|