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 ): iterable { 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(); return $stmt->getResult()->getIterator(BanInfo::fromResult(...)); } 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 BanInfo::fromResult($result); } public function countActiveBans( UserInfo|string $userInfo, int $minimumSeverity = self::SEVERITY_MIN ): int { if($userInfo instanceof UserInfo) $userInfo = $userInfo->getId(); // orders by ban_expires descending with NULLs (permanent) first $stmt = $this->cache->get('SELECT COUNT(*) 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() ? $result->getInteger(0) : 0; } 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() ? BanInfo::fromResult($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(); } }