misuzu/src/Users/Bans.php
flash 383e2ed0e0 Rewrote the user information class.
This one took multiple days and it pretty invasive into the core of Misuzu so issue might (will) arise, there's also some features that have gone temporarily missing in the mean time and some inefficiencies introduced that will be fixed again at a later time.
The old class isn't gone entirely because I still have to figure out what I'm gonna do about validation, but for the most part this knocks out one of the "layers of backwards compatibility", as I've been referring to it, and is moving us closer to a future where Flashii actually gets real updates.
If you run into anything that's broken and you're inhibited from reporting it through the forum, do it through chat or mail me at flashii-issues@flash.moe.
2023-08-02 22:12:47 +00:00

195 lines
6.7 KiB
PHP

<?php
namespace Misuzu\Users;
use InvalidArgumentException;
use RuntimeException;
use Index\DateTime;
use Index\Data\DbStatementCache;
use Index\Data\DbTools;
use Index\Data\IDbConnection;
use Misuzu\Pagination;
class Bans {
public const SEVERITY_MAX = 10;
public const SEVERITY_MIN = -10;
public const SEVERITY_DEFAULT = 0;
private IDbConnection $dbConn;
private DbStatementCache $cache;
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
public function countBans(
UserInfo|string|null $userInfo = null,
?bool $activeOnly = null
): int {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->getId();
$hasUserInfo = $userInfo !== null;
$hasActiveOnly = $activeOnly !== null;
$args = 0;
$query = 'SELECT COUNT(*) FROM msz_users_bans';
if($hasActiveOnly) {
++$args;
if($activeOnly)
$query .= ' WHERE ban_expires IS NULL OR ban_expires > NOW()';
else
$query .= ' WHERE ban_expires <= NOW()';
}
if($hasUserInfo)
$query .= sprintf(' %s user_id = ?', ++$args > 1 ? 'AND' : 'WHERE');
$args = 0;
$stmt = $this->cache->get($query);
if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo);
$stmt->execute();
$result = $stmt->getResult();
$count = 0;
if($result->next())
$count = $result->getInteger(0);
return $count;
}
public function getBans(
UserInfo|string|null $userInfo = null,
?bool $activeOnly = null,
?bool $activeFirst = null,
?Pagination $pagination = null
): array {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->getId();
$hasUserInfo = $userInfo !== null;
$hasActiveOnly = $activeOnly !== null;
$hasActiveFirst = $activeFirst !== null;
$hasPagination = $pagination !== null;
$args = 0;
$query = 'SELECT ban_id, user_id, mod_id, ban_severity, ban_reason_public, ban_reason_private, UNIX_TIMESTAMP(ban_created), UNIX_TIMESTAMP(ban_expires) FROM msz_users_bans';
if($hasActiveOnly) {
++$args;
if($activeOnly)
$query .= ' WHERE ban_expires IS NULL OR ban_expires > NOW()';
else
$query .= ' WHERE ban_expires <= NOW()';
}
if($hasUserInfo)
$query .= sprintf(' %s user_id = ?', ++$args > 1 ? 'AND' : 'WHERE');
$query .= ' ORDER BY ';
if($hasActiveFirst)
$query .= sprintf('ban_expires IS NULL %1$s, ban_expires %1$s', $activeFirst ? 'DESC' : 'ASC');
else $query .= 'ban_created DESC';
if($hasPagination)
$query .= ' LIMIT ? OFFSET ?';
$args = 0;
$stmt = $this->cache->get($query);
if($hasUserInfo)
$stmt->addParameter(++$args, $userInfo);
if($hasPagination) {
$stmt->addParameter(++$args, $pagination->getRange());
$stmt->addParameter(++$args, $pagination->getOffset());
}
$stmt->execute();
$result = $stmt->getResult();
$bans = [];
while($result->next())
$bans[] = new BanInfo($result);
return $bans;
}
public function getBan(string $banId): BanInfo {
$stmt = $this->cache->get('SELECT ban_id, user_id, mod_id, ban_severity, ban_reason_public, ban_reason_private, UNIX_TIMESTAMP(ban_created), UNIX_TIMESTAMP(ban_expires) FROM msz_users_bans WHERE ban_id = ?');
$stmt->addParameter(1, $banId);
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
throw new RuntimeException('No ban with ID $banId found.');
return new BanInfo($result);
}
public function tryGetActiveBan(
UserInfo|string $userInfo,
int $minimumSeverity = self::SEVERITY_MIN
): ?BanInfo {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->getId();
// orders by ban_expires descending with NULLs (permanent) first
$stmt = $this->cache->get('SELECT ban_id, user_id, mod_id, ban_severity, ban_reason_public, ban_reason_private, UNIX_TIMESTAMP(ban_created), UNIX_TIMESTAMP(ban_expires) FROM msz_users_bans WHERE user_id = ? AND ban_severity >= ? AND (ban_expires IS NULL OR ban_expires > NOW()) ORDER BY ban_expires IS NULL DESC, ban_expires DESC');
$stmt->addParameter(1, $userInfo);
$stmt->addParameter(2, $minimumSeverity);
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? new BanInfo($result) : null;
}
public function createBan(
UserInfo|string $userInfo,
DateTime|int|null $expires,
string $publicReason,
string $privateReason,
int $severity = self::SEVERITY_DEFAULT,
UserInfo|string|null $modInfo = null
): BanInfo {
if($severity < self::SEVERITY_MIN || $severity > self::SEVERITY_MAX)
throw new InvalidArgumentException('$severity may not be less than -10 or more than 10.');
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->getId();
if($modInfo instanceof UserInfo)
$modInfo = $modInfo->getId();
if($expires instanceof DateTime)
$expires = $expires->getUnixTimeSeconds();
$stmt = $this->cache->get('INSERT INTO msz_users_bans (user_id, mod_id, ban_severity, ban_reason_public, ban_reason_private, ban_expires) VALUES (?, ?, ?, ?, ?, FROM_UNIXTIME(?))');
$stmt->addParameter(1, $userInfo);
$stmt->addParameter(2, $modInfo);
$stmt->addParameter(3, $severity);
$stmt->addParameter(4, $publicReason);
$stmt->addParameter(5, $privateReason);
$stmt->addParameter(6, $expires);
$stmt->execute();
return $this->getBan((string)$this->dbConn->getLastInsertId());
}
public function deleteBans(BanInfo|string|array $banInfos): void {
if(!is_array($banInfos))
$banInfos = [$banInfos];
elseif(empty($banInfos))
return;
$stmt = $this->cache->get(sprintf(
'DELETE FROM msz_users_bans WHERE ban_id IN (%s)',
DbTools::prepareListString($banInfos)
));
$args = 0;
foreach($banInfos as $banInfo) {
if($banInfo instanceof BanInfo)
$banInfo = $banInfo->getId();
elseif(!is_string($banInfo))
throw new InvalidArgumentException('$banInfos must be strings of instances of BanInfo.');
$stmt->addParameter(++$args, $banInfo);
}
$stmt->execute();
}
}