seria/src/Torrents/Torrents.php

162 lines
6.1 KiB
PHP

<?php
namespace Seria\Torrents;
use InvalidArgumentException;
use RuntimeException;
use Index\Data\DbStatementCache;
use Index\Data\IDbConnection;
use Seria\Users\UserInfo;
class Torrents {
private IDbConnection $dbConn;
private DbStatementCache $cache;
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
public function getTorrents(
?bool $public = null,
?bool $approved = null,
UserInfo|string|null $userInfo = null,
int $startAt = -1,
int $take = -1
): array {
$hasPublic = $public !== null;
$hasApproved = $approved !== null;
$hasUserInfo = $userInfo !== null;
$hasStartAt = $startAt > 0;
$hasTake = $take > 0;
$args = 0;
$query = 'SELECT torrent_id, user_id, torrent_hash, torrent_active, torrent_name, UNIX_TIMESTAMP(torrent_created), UNIX_TIMESTAMP(torrent_approved), torrent_piece_length, torrent_private, torrent_comment FROM ser_torrents';
if($hasPublic) {
++$args;
$query .= sprintf(' WHERE torrent_private %s 0', $public ? '=' : '<>');
}
if($hasApproved)
$query .= sprintf(' %s torrent_approved %s NULL', ++$args > 1 ? 'AND' : 'WHERE', $approved ? 'IS NOT' : 'IS');
if($hasUserInfo)
$query .= sprintf(' %s user_id = ?', ++$args > 1 ? 'AND' : 'WHERE');
if($hasStartAt)
$query .= sprintf(' %s torrent_id < ?', ++$args > 1 ? 'AND' : 'WHERE');
$query .= ' ORDER BY torrent_id DESC';
if($hasTake)
$query .= ' LIMIT ?';
$args = 0;
$stmt = $this->cache->get($query);
if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
if($hasStartAt)
$stmt->addParameter(++$args, $startAt);
if($hasTake)
$stmt->addParameter(++$args, $take);
$stmt->execute();
$torrents = [];
$result = $stmt->getResult();
while($result->next())
$torrents[] = new TorrentInfo($result);
return $torrents;
}
public const GET_TORRENT_ID = 0x01;
public const GET_TORRENT_HASH = 0x02;
private const GET_TORRENT_SELECT_ALIASES = [
'id' => self::GET_TORRENT_ID,
'hash' => self::GET_TORRENT_HASH,
];
public static function resolveGetTorrentSelectAlias(int|string $select): int {
if(is_string($select)) {
if(!array_key_exists($select, self::GET_TORRENT_SELECT_ALIASES))
throw new InvalidArgumentException('Invalid $select alias.');
$select = self::GET_TORRENT_SELECT_ALIASES[$select];
} elseif($select === 0)
throw new InvalidArgumentException('$select may not be zero.');
return $select;
}
public function getTorrent(string $value, int|string $select = self::GET_TORRENT_ID): TorrentInfo {
if($value === '')
throw new InvalidArgumentException('$value may not be empty.');
$select = self::resolveGetTorrentSelectAlias($select);
$selectId = ($select & self::GET_TORRENT_ID) > 0;
$selectHash = ($select & self::GET_TORRENT_HASH) > 0;
if(!$selectId && !$selectHash)
throw new InvalidArgumentException('$select flagset is invalid.');
$args = 0;
$query = 'SELECT torrent_id, user_id, torrent_hash, torrent_active, torrent_name, UNIX_TIMESTAMP(torrent_created), UNIX_TIMESTAMP(torrent_approved), torrent_piece_length, torrent_private, torrent_comment FROM ser_torrents';
if($selectId) {
++$args;
$query .= ' WHERE torrent_id = ?';
}
if($selectHash)
$query .= sprintf(' %s torrent_hash = ?', ++$args > 1 ? 'OR' : 'WHERE');
$args = 0;
$stmt = $this->cache->get($query);
if($selectId)
$stmt->addParameter(++$args, $value);
if($selectHash)
$stmt->addParameter(++$args, $value);
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
throw new RuntimeException('Download info not found.');
return new TorrentInfo($result);
}
public function createTorrent(
UserInfo|string|null $userInfo,
string $infoHash,
string $name,
int $created,
int $pieceLength,
bool $isPrivate,
string $comment
): string {
$stmt = $this->cache->get('INSERT INTO ser_torrents (user_id, torrent_hash, torrent_name, torrent_created, torrent_piece_length, torrent_private, torrent_comment) VALUES (?, ?, ?, FROM_UNIXTIME(?), ?, ?, ?)');
$stmt->addParameter(1, $userInfo === null ? null : ($userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo));
$stmt->addParameter(2, $infoHash);
$stmt->addParameter(3, $name);
$stmt->addParameter(4, $created);
$stmt->addParameter(5, $pieceLength);
$stmt->addParameter(6, $isPrivate ? 1 : 0);
$stmt->addParameter(7, $comment);
$stmt->execute();
return (string)$this->dbConn->getLastInsertId();
}
public function updateTorrentInfoHash(TorrentInfo|string $torrentInfo, string $infoHash): void {
$stmt = $this->cache->get('UPDATE ser_torrents SET torrent_hash = ? WHERE torrent_id = ?');
$stmt->addParameter(1, $infoHash);
$stmt->addParameter(2, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->execute();
}
public function approveTorrent(TorrentInfo|string $torrentInfo): void {
$stmt = $this->cache->get('UPDATE ser_torrents SET torrent_approved = COALESCE(torrent_approved, NOW()) WHERE torrent_id = ?');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->execute();
}
public function deleteTorrent(TorrentInfo|string $torrentInfo): void {
$stmt = $this->cache->get('DELETE FROM ser_torrents WHERE torrent_id = ?');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->execute();
}
}