misuzu/src/Users/Warnings.php

169 lines
5.4 KiB
PHP

<?php
namespace Misuzu\Users;
use InvalidArgumentException;
use RuntimeException;
use Index\Data\DbStatementCache;
use Index\Data\DbTools;
use Index\Data\IDbConnection;
use Misuzu\Pagination;
// this system is currently kinda useless because it only silently shows up on profiles
// planning a notification system anyway so that should probably hook into
class Warnings {
public const VISIBLE_BACKLOG = 90 * 24 * 60 * 60;
private IDbConnection $dbConn;
private DbStatementCache $cache;
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
public function countWarnings(
UserInfo|string|null $userInfo = null,
?int $backlog = null
): int {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->getId();
$hasUserInfo = $userInfo !== null;
$hasBacklog = $backlog !== null;
$args = 0;
$query = 'SELECT COUNT(*) FROM msz_users_warnings';
if($hasUserInfo) {
++$args;
$query .= ' WHERE user_id = ?';
}
if($hasBacklog) {
if($backlog < 1)
throw new InvalidArgumentException('$backlog must be either null to disable it or be greater than 0.');
$query .= sprintf(' %s warn_created > NOW() - INTERVAL ? SECOND', ++$args > 1 ? 'AND' : 'WHERE');
}
$args = 0;
$stmt = $this->cache->get($query);
if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo);
if($hasBacklog)
$stmt->addParameter(++$args, $backlog);
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) : 0;
}
public function getWarningsWithDefaultBacklog(
UserInfo|string|null $userInfo = null,
?Pagination $pagination = null
): iterable {
return $this->getWarnings(
$userInfo,
self::VISIBLE_BACKLOG,
$pagination
);
}
public function getWarnings(
UserInfo|string|null $userInfo = null,
?int $backlog = null,
?Pagination $pagination = null
): iterable {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->getId();
$hasUserInfo = $userInfo !== null;
$hasBacklog = $backlog !== null;
$hasPagination = $pagination !== null;
$args = 0;
$query = 'SELECT warn_id, user_id, mod_id, warn_body, UNIX_TIMESTAMP(warn_created) FROM msz_users_warnings';
if($hasUserInfo) {
++$args;
$query .= ' WHERE user_id = ?';
}
if($hasBacklog) {
if($backlog < 1)
throw new InvalidArgumentException('$backlog must be either null to disable it or be greater than 0.');
$query .= sprintf(' %s warn_created > NOW() - INTERVAL ? SECOND', ++$args > 1 ? 'AND' : 'WHERE');
}
$query .= ' ORDER BY warn_created DESC';
if($hasPagination)
$query .= ' LIMIT ? OFFSET ?';
$args = 0;
$stmt = $this->cache->get($query);
if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo);
if($hasBacklog)
$stmt->addParameter(++$args, $backlog);
if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange());
$stmt->addParameter(++$args, $pagination->getOffset());
}
$stmt->execute();
return $stmt->getResult()->getIterator(WarningInfo::fromResult(...));
}
public function getWarning(string $warnId): WarningInfo {
$stmt = $this->cache->get('SELECT warn_id, user_id, mod_id, warn_body, UNIX_TIMESTAMP(warn_created) FROM msz_users_warnings WHERE warn_id = ?');
$stmt->addParameter(1, $warnId);
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
throw new RuntimeException('Could not find warning info for ID $warnId.');
return WarningInfo::fromResult($result);
}
public function createWarning(
UserInfo|string $userInfo,
string $body,
UserInfo|string|null $modInfo
): WarningInfo {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->getId();
if($modInfo instanceof UserInfo)
$modInfo = $modInfo->getId();
$stmt = $this->cache->get('INSERT INTO msz_users_warnings (user_id, mod_id, warn_body) VALUES (?, ?, ?)');
$stmt->addParameter(1, $userInfo);
$stmt->addParameter(2, $modInfo);
$stmt->addParameter(3, $body);
$stmt->execute();
return $this->getWarning((string)$this->dbConn->getLastInsertId());
}
public function deleteWarnings(WarningInfo|string|array $warnInfos): void {
if(!is_array($warnInfos))
$warnInfos = [$warnInfos];
elseif(empty($warnInfos))
return;
$stmt = $this->cache->get(sprintf(
'DELETE FROM msz_users_warnings WHERE warn_id IN (%s)',
DbTools::prepareListString($warnInfos)
));
$args = 0;
foreach($warnInfos as $warnInfo) {
if($warnInfo instanceof WarningInfo)
$warnInfo = $warnInfo->getId();
elseif(!is_string($warnInfo))
throw new InvalidArgumentException('$warnInfos must be strings of instances of WarningInfo.');
$stmt->addParameter(++$args, $warnInfo);
}
$stmt->execute();
}
}