Files
ops-Gazelle/sections/torrents/browse.php
2025-08-27 16:44:43 +02:00

308 lines
12 KiB
PHP

<?php
/** @phpstan-var \Gazelle\User $Viewer */
/** @phpstan-var \Twig\Environment $Twig */
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
// phpcs:disable Generic.WhiteSpace.ScopeIndent.Incorrect
declare(strict_types=1);
namespace Gazelle;
$tagMan = new Manager\Tag();
$tgMan = new Manager\TGroup();
$torMan = new Manager\Torrent();
$reportMan = new Manager\Torrent\Report($torMan);
$snatcher = $Viewer->snatch();
if (!empty($_GET['searchstr']) || !empty($_GET['groupname'])) {
$torrent = $torMan->findByInfohash($_GET['searchstr'] ?? $_GET['groupname']);
if ($torrent) {
header('Location: ' . $torrent->location());
exit;
}
}
$imgTag = '<img loading="lazy" src="' . new User\Stylesheet($Viewer)->imagePath() . '%s.png" class="tooltip" alt="%s" title="%s"/>';
$headerMap = [
'year' => ['defaultSort' => 'desc', 'text' => 'Year'],
'time' => ['defaultSort' => 'desc', 'text' => 'Created', 'dbColumn' => 'created'],
'size' => ['defaultSort' => 'desc', 'text' => 'Size'],
'snatched' => ['defaultSort' => 'desc', 'text' => sprintf($imgTag, 'snatched', 'Snatches', 'Snatches')],
'seeders' => ['defaultSort' => 'desc', 'text' => sprintf($imgTag, 'seeders', 'Seeders', 'Seeders')],
'leechers' => ['defaultSort' => 'desc', 'text' => sprintf($imgTag, 'leechers', 'Leechers', 'Leechers')],
];
$header = new Util\SortableTableHeader('time', $headerMap);
$headerIcons = new Util\SortableTableHeader('time', $headerMap, ['asc' => '', 'desc' => '']);
if (isset($_GET['setdefault'])) {
// Setting default search options, remove page and setdefault params
$clear = '/(?:&|^)(?:page|setdefault)=.*?(?:&|$)/';
$Viewer->modifyOption('DefaultSearch', preg_replace($clear, '', $_SERVER['QUERY_STRING']));
} elseif (isset($_GET['cleardefault'])) {
// Clearing default search options
$Viewer->modifyOption('DefaultSearch', null);
} elseif ($Viewer->option('DefaultSearch') && (count($_GET) === 0 || (isset($_GET['page']) && count($_GET) === 1))) {
// Use default search options
$page = $_GET['page'] ?? false;
parse_str($Viewer->option('DefaultSearch'), $_GET);
if ($page !== false) {
$_GET['page'] = $page;
}
}
// Terms were not submitted via the search form
if (isset($_GET['searchsubmit'])) {
$GroupResults = !empty($_GET['group_results']);
} else {
$GroupResults = (bool)$Viewer->option('DisableGrouping2') === false;
}
if (!isset($_GET['tags_type'])) {
$_GET['tags_type'] = '1';
}
$paginator = new Util\Paginator(TORRENTS_PER_PAGE, (int)($_GET['page'] ?? 1));
$Search = new Search\Torrent(
$GroupResults,
$header->orderKey(),
$header->dir(),
$paginator->page(),
TORRENTS_PER_PAGE,
$Viewer->permitted('site_search_many'),
);
$Results = $Search->query($_GET);
if ($Results == false) {
$Results = [];
} else {
// bleah
$Results = array_map('intval', $Results);
}
if ($GroupResults) {
// FIXME: is this even needed?
$Results = array_unique($Results);
}
$RealNumResults = $NumResults = $Search->record_count();
if (!$Viewer->permitted('site_search_many')) {
$NumResults = min($NumResults, SPHINX_MAX_MATCHES);
}
$paginator->setTotal($NumResults);
/* if the user has the privilege of advanced search, we prioritze the url param 'action'
* if it is present, otherwise we fall back to their personal preference.
*/
$advancedSearch = $Viewer->permitted('site_advanced_search')
&& ($_GET['action'] ?? ['basic ', 'advanced'][$Viewer->option('SearchType') ?? 0])
== 'advanced';
echo $Twig->render('torrent/browse-header.twig', [
'input' => $_GET,
'filtered' => $Search->has_filters(),
'grouped' => $GroupResults,
'release_type' => new ReleaseType()->list(),
'results_total' => $RealNumResults,
'results_shown' => $NumResults,
'show_basic' => !$advancedSearch,
'show_remaster' =>
isset($_GET['remastercataloguenumber'])
|| isset($_GET['remasterrecordlabel'])
|| isset($_GET['remastertitle'])
|| isset($_GET['remasteryear']),
'show_search' => (bool)$Viewer->option('ShowTorFilter'),
'tag_default' => $tagMan->genreList(),
'tag_list' => $Search->get_terms('taglist'),
'viewer' => $Viewer,
]);
if ($NumResults == 0) {
echo $Twig->render('torrent/search-none.twig', [
'list' => $tagMan->userTopTagList($Viewer),
]);
exit;
}
$releaseTypes = new ReleaseType()->list();
$bookmark = new \Gazelle\User\Bookmark($Viewer);
$imgProxy = new Util\ImageProxy($Viewer);
echo $paginator->linkbox();
?>
<table class="torrent_table cats <?=$GroupResults ? 'grouping' : 'no_grouping'?> m_table" id="torrent_table">
<tr class="colhead">
<?php if ($GroupResults) { ?>
<td class="small"></td>
<?php } ?>
<td class="small cats_col"></td>
<td class="m_th_left m_th_left_collapsable nobr" width="100%">Name / <?= $header->emit('year') ?></td>
<td class="nobr"><?= $header->emit('time') ?></td>
<?php if ($Viewer->ordinal()->value('file-count-display')) { ?>
<td class="number_column">Files</td>
<?php } ?>
<td class="number_column nobr"><?= $header->emit('size') ?></td>
<td class="sign nobr snatches"><?= $headerIcons->emit('snatched') ?></td>
<td class="sign nobr seeders"><?= $headerIcons->emit('seeders') ?></td>
<td class="sign nobr leechers"><?= $headerIcons->emit('leechers') ?></td>
</tr>
<?php
$groupsClosed = (bool)$Viewer->option('TorrentGrouping');
foreach ($Results as $Key => $GroupID) {
$tgroup = $tgMan->findById($GroupID);
if (is_null($tgroup)) {
continue;
}
if ($GroupResults) {
$torrentList = $tgroup->torrentIdList();
if (empty($torrentList)) {
continue;
}
} else {
$torrentList = [$Key];
}
$SnatchedGroupClass = $tgroup->isSnatched() ? ' snatched_group' : '';
if ($GroupResults && (count($torrentList) > 1 || $tgroup->categoryGrouped())) {
?>
<tr class="group groupid_<?=$GroupID?>_header<?=$SnatchedGroupClass?>">
<?= $Twig->render('tgroup/collapse-tgroup.twig', ['closed' => $groupsClosed, 'id' => $tgroup->id]) ?>
<td class="center cats_col">
<div title="<?= $tgroup->primaryTag() ?>" class="tooltip <?= $tgroup->categoryCss() ?> <?= $tgroup->primaryTagCss() ?>">
</div>
</td>
<td class="td_info big_info">
<?php if ($Viewer->option('CoverArt')) { ?>
<div class="group_image float_left clear">
<?= $imgProxy->tgroupThumbnail($tgroup) ?>
</div>
<?php } ?>
<div class="group_info clear">
<?= $tgroup->link() ?>
<span style="float: right">
<?= $Twig->render('bookmark/action.twig', [
'class' => 'torrent',
'id' => $tgroup->id,
'is_bookmarked' => $bookmark->isTGroupBookmarked($tgroup),
]) ?>
</span>
<br />
<div class="tags"><?= implode(', ',
array_map(fn ($name) => "<a href=\"torrents.php?action="
. ($advancedSearch ? 'advanced' : 'basic')
. "&amp;taglist=$name\">$name</a>", $tgroup->tagNameList())
) ?></div>
</div>
</td>
<td class="td_time nobr"><?=time_diff($tgroup->mostRecentUpload(), 1)?></td>
<?php if ($Viewer->ordinal()->value('file-count-display')) { ?>
<td></td>
<?php } ?>
<td class="td_size number_column nobr"><?= byte_format($tgroup->maxTorrentSize()) ?> (Max)</td>
<td class="td_snatched number_column m_td_right"><?=number_format($tgroup->stats()->snatchTotal())?></td>
<td class="td_seeders number_column<?= $tgroup->stats()->seedingTotal() == 0 ? ' r00' : '' ?> m_td_right"><?=number_format($tgroup->stats()->seedingTotal())?></td>
<td class="td_leechers number_column m_td_right"><?=number_format($tgroup->stats()->leechTotal())?></td>
</tr>
<?php
$prev = '';
$EditionID = 0;
$UnknownCounter = 0;
$prevPrimaryTotal = null;
foreach ($torrentList as $torrentId) {
$torrent = $torMan->findById($torrentId);
if (is_null($torrent)) {
continue;
}
$current = $torrent->remasterTuple();
if ($torrent->isRemasteredUnknown()) {
$UnknownCounter++;
}
if ($prev != $current || $UnknownCounter === 1) {
$EditionID++;
?>
<tr class="group_torrent groupid_<?=$tgroup->id?> edition<?=$SnatchedGroupClass . ($groupsClosed ? ' hidden' : '')?>">
<td colspan="<?= $Viewer->ordinal()->value('file-count-display') ? 9 : 8 ?>" class="edition_info">
<?= $Twig->render('torrent/edition-header.twig', [
'edition_id' => $EditionID,
'tgroup' => $tgroup,
'torrent' => $torrent,
]) ?>
</td>
</tr>
<?php
}
$prev = $current;
$SnatchedTorrentClass = $snatcher->showSnatch($torrent) ? ' snatched_torrent' : '';
?>
<tr class="group_torrent groupid_<?=$tgroup->id?> edition_<?=$EditionID?><?=$SnatchedTorrentClass . $SnatchedGroupClass . ($groupsClosed ? ' hidden' : '')?>">
<td class="td_info" colspan="3">
<?= $Twig->render('torrent/action-v2.twig', [
'pl' => true,
'js' => true,
'torrent' => $torrent,
'viewer' => $Viewer,
]) ?>
&raquo; <?= $torrent->shortLabelLink() ?>
</td>
<td class="td_time nobr"><?=time_diff($torrent->created(), 1)?></td>
<?= $Twig->render('torrent/stats.twig', [
'prev_primary' => $prevPrimaryTotal,
'torrent' => $torrent,
'viewer' => $Viewer,
]) ?>
</tr>
<?php
$prevPrimaryTotal = $torrent->fileListPrimaryTotal();
}
} else {
// Viewing a type that does not require grouping
foreach ($torrentList as $torrentId) {
$torrent = $torMan->findById($torrentId);
if (is_null($torrent)) {
continue;
}
$SnatchedTorrentClass = $tgroup->isSnatched() ? ' snatched_torrent' : '';
?>
<tr class="torrent<?=$SnatchedTorrentClass . $SnatchedGroupClass?>">
<?php if ($GroupResults) { ?>
<td></td>
<?php } ?>
<td class="center cats_col m_cats_col m_td_left">
<div title="<?= $tgroup->primaryTag() ?>" class="tooltip <?= $tgroup->categoryCss() ?> <?= $tgroup->primaryTagCss() ?>"></div>
</td>
<td class="td_info big_info">
<?php if ($Viewer->option('CoverArt')) { ?>
<div class="group_image float_left clear">
<?= $imgProxy->tgroupThumbnail($tgroup) ?>
</div>
<?php } ?>
<div class="group_info clear">
<?= $Twig->render('torrent/action-v2.twig', [
'torrent' => $torrent,
'viewer' => $Viewer,
]) ?>
<?= $torrent->fullLink() ?>
<div class="tags"><?= implode(', ',
array_map(fn ($name) => "<a href=\"torrents.php?action="
. ($advancedSearch ? 'advanced' : 'basic')
. "&amp;taglist=$name\">$name</a>", $tgroup->tagNameList())
) ?></div>
</div>
</td>
<td class="td_time nobr"><?=time_diff($torrent->created(), 1)?></td>
<?= $Twig->render('torrent/stats.twig', ['torrent' => $torrent, 'viewer' => $Viewer]) ?>
</tr>
<?php
}
}
}
?>
</table>
<?= $paginator->linkbox() ?>
</div>
<?php
View::show_footer();