194 lines
6.7 KiB
PHP
194 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;
|
||
|
use Misuzu\Users\User;
|
||
|
|
||
|
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(
|
||
|
User|string|null $userInfo = null,
|
||
|
?bool $activeOnly = null
|
||
|
): int {
|
||
|
if($userInfo instanceof User)
|
||
|
$userInfo = (string)$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(
|
||
|
User|string|null $userInfo = null,
|
||
|
?bool $activeOnly = null,
|
||
|
?bool $activeFirst = null,
|
||
|
?Pagination $pagination = null
|
||
|
): array {
|
||
|
if($userInfo instanceof User)
|
||
|
$userInfo = (string)$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(
|
||
|
User|string $userInfo,
|
||
|
int $minimumSeverity = self::SEVERITY_MIN
|
||
|
): ?BanInfo {
|
||
|
if($userInfo instanceof User)
|
||
|
$userInfo = (string)$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(
|
||
|
User|string $userInfo,
|
||
|
DateTime|int|null $expires,
|
||
|
string $publicReason,
|
||
|
string $privateReason,
|
||
|
int $severity = self::SEVERITY_DEFAULT,
|
||
|
User|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 User)
|
||
|
$userInfo = (string)$userInfo->getId();
|
||
|
if($modInfo instanceof User)
|
||
|
$modInfo = (string)$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];
|
||
|
|
||
|
$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();
|
||
|
}
|
||
|
}
|