'Note', MSZ_WARN_WARNING => 'Warning', MSZ_WARN_SILENCE => 'Silence', MSZ_WARN_BAN => 'Ban', ]); function user_warning_type_is_valid(int $type): bool { return in_array($type, MSZ_WARN_TYPES, true); } function user_warning_type_get_name(int $type): string { return user_warning_type_is_valid($type) ? MSZ_WARN_TYPE_NAMES[$type] : ''; } function user_warning_get_types(): array { return MSZ_WARN_TYPE_NAMES; } function user_warning_has_duration(int $type): bool { return in_array($type, MSZ_WARN_TYPES_HAS_DURATION, true); } define('MSZ_E_WARNING_ADD_DB', -1); define('MSZ_E_WARNING_ADD_TYPE', -2); define('MSZ_E_WARNING_ADD_USER', -3); define('MSZ_E_WARNING_ADD_DURATION', -4); function user_warning_add( int $userId, string $userIp, int $issuerId, string $issuerIp, int $type, string $publicNote, string $privateNote, ?int $duration = null ): int { if (!user_warning_type_is_valid($type)) { return MSZ_E_WARNING_ADD_TYPE; } if ($userId < 1) { return MSZ_E_WARNING_ADD_USER; } if (user_warning_has_duration($type)) { if ($duration <= time()) { return MSZ_E_WARNING_ADD_DURATION; } } else { $duration = 0; } $addWarning = db_prepare(' INSERT INTO `msz_user_warnings` (`user_id`, `user_ip`, `issuer_id`, `issuer_ip`, `warning_type`, `warning_note`, `warning_note_private`, `warning_duration`) VALUES (:user_id, INET6_ATON(:user_ip), :issuer_id, INET6_ATON(:issuer_ip), :type, :note, :note_private, :duration) '); $addWarning->bindValue('user_id', $userId); $addWarning->bindValue('user_ip', $userIp); $addWarning->bindValue('issuer_id', $issuerId); $addWarning->bindValue('issuer_ip', $issuerIp); $addWarning->bindValue('type', $type); $addWarning->bindValue('note', $publicNote); $addWarning->bindValue('note_private', $privateNote); $addWarning->bindValue('duration', $duration < 1 ? null : date('Y-m-d H:i:s', $duration)); if (!$addWarning->execute()) { return MSZ_E_WARNING_ADD_DB; } return (int)db_last_insert_id(); } function user_warning_count(int $userId): int { if ($userId < 1) { return 0; } $countWarnings = db_prepare(' SELECT COUNT(`warning_id`) FROM `msz_user_warnings` WHERE `user_id` = :user_id '); $countWarnings->bindValue('user_id', $userId); return (int)($countWarnings->execute() ? $countWarnings->fetchColumn() : 0); } function user_warning_remove(int $warningId): bool { if ($warningId < 1) { return false; } $removeWarning = db_prepare(' DELETE FROM `msz_user_warnings` WHERE `warning_id` = :warning_id '); $removeWarning->bindValue('warning_id', $warningId); return $removeWarning->execute(); } function user_warning_fetch( int $userId, ?int $days = null, array $displayTypes = MSZ_WARN_TYPES ): array { $fetchWarnings = db_prepare(sprintf( ' SELECT uw.`warning_id`, uw.`warning_created`, uw.`warning_type`, uw.`warning_note`, uw.`warning_note_private`, uw.`user_id`, uw.`issuer_id`, uw.`warning_duration`, INET6_NTOA(uw.`user_ip`) AS `user_ip`, INET6_NTOA(uw.`issuer_ip`) AS `issuer_ip`, iu.`username` AS `issuer_username` FROM `msz_user_warnings` AS uw LEFT JOIN `msz_users` AS iu ON iu.`user_id` = uw.`issuer_id` WHERE uw.`user_id` = :user_id AND uw.`warning_type` IN (%1$s) %2$s ORDER BY uw.`warning_id` DESC ', implode(',', array_apply($displayTypes, 'intval')), $days !== null ? 'AND (uw.`warning_created` >= NOW() - INTERVAL :days DAY OR (uw.`warning_duration` IS NOT NULL AND uw.`warning_duration` > NOW()))' : '' )); $fetchWarnings->bindValue('user_id', $userId); if ($days !== null) { $fetchWarnings->bindValue('days', $days); } return db_fetch_all($fetchWarnings); } function user_warning_global_count(?int $userId = null): int { $countWarnings = db_prepare(sprintf(' SELECT COUNT(`warning_id`) FROM `msz_user_warnings` %s ', $userId > 0 ? 'WHERE `user_id` = :user_id' : '')); if ($userId > 0) { $countWarnings->bindValue('user_id', $userId); } return (int)($countWarnings->execute() ? $countWarnings->fetchColumn() : 0); } function user_warning_global_fetch(int $offset = 0, int $take = 50, ?int $userId = null): array { $fetchWarnings = db_prepare(sprintf( ' SELECT uw.`warning_id`, uw.`warning_created`, uw.`warning_type`, uw.`warning_note`, uw.`warning_note_private`, uw.`user_id`, uw.`issuer_id`, uw.`warning_duration`, INET6_NTOA(uw.`user_ip`) AS `user_ip`, INET6_NTOA(uw.`issuer_ip`) AS `issuer_ip`, iu.`username` AS `issuer_username`, wu.`username` AS `username` FROM `msz_user_warnings` AS uw LEFT JOIN `msz_users` AS iu ON iu.`user_id` = uw.`issuer_id` LEFT JOIN `msz_users` AS wu ON wu.`user_id` = uw.`user_id` %1$s ORDER BY uw.`warning_id` DESC LIMIT :offset, :take ', $userId > 0 ? 'WHERE uw.`user_id` = :user_id' : '' )); $fetchWarnings->bindValue('offset', $offset); $fetchWarnings->bindValue('take', $take); if ($userId > 0) { $fetchWarnings->bindValue('user_id', $userId); } return db_fetch_all($fetchWarnings); } function user_warning_check_ip(string $address): bool { $checkAddress = db_prepare(sprintf( ' SELECT COUNT(`warning_id`) > 0 FROM `msz_user_warnings` WHERE `warning_type` IN (%s) AND `user_ip` = INET6_ATON(:address) AND `warning_duration` IS NOT NULL AND `warning_duration` >= NOW() ', implode(',', MSZ_WARN_TYPES_HAS_DURATION) )); $checkAddress->bindValue('address', $address); return (bool)($checkAddress->execute() ? $checkAddress->fetchColumn() : false); } define('MSZ_WARN_EXPIRATION_CACHE', '_msz_user_warning_expiration'); function user_warning_check_expiration(int $userId, int $type): int { if ($userId < 1 || !user_warning_has_duration($type)) { return 0; } if (!isset($GLOBALS[MSZ_WARN_EXPIRATION_CACHE]) || !is_array($GLOBALS[MSZ_WARN_EXPIRATION_CACHE])) { $GLOBALS[MSZ_WARN_EXPIRATION_CACHE] = []; } elseif (array_key_exists($type, $GLOBALS[MSZ_WARN_EXPIRATION_CACHE]) && array_key_exists($userId, $GLOBALS[MSZ_WARN_EXPIRATION_CACHE][$type])) { return $GLOBALS[MSZ_WARN_EXPIRATION_CACHE][$type][$userId]; } $getExpiration = db_prepare(' SELECT `warning_duration` FROM `msz_user_warnings` WHERE `warning_type` = :type AND `user_id` = :user AND `warning_duration` IS NOT NULL AND `warning_duration` >= NOW() ORDER BY `warning_duration` DESC LIMIT 1 '); $getExpiration->bindValue('type', $type); $getExpiration->bindValue('user', $userId); $expiration = $getExpiration->execute() ? $getExpiration->fetchColumn() : ''; return $GLOBALS[MSZ_WARN_EXPIRATION_CACHE][$type][$userId] = (empty($expiration) ? 0 : strtotime($expiration)); } define('MSZ_WARN_RESTRICTION_CACHE', '_msz_user_warning_restriction'); function user_warning_check_restriction(int $userId): bool { if ($userId < 1) { return false; } if (!isset($GLOBALS[MSZ_WARN_RESTRICTION_CACHE]) || !is_array($GLOBALS[MSZ_WARN_RESTRICTION_CACHE])) { $GLOBALS[MSZ_WARN_RESTRICTION_CACHE] = []; } elseif (array_key_exists($userId, $GLOBALS[MSZ_WARN_RESTRICTION_CACHE])) { return $GLOBALS[MSZ_WARN_RESTRICTION_CACHE][$userId]; } $checkAddress = db_prepare(sprintf( ' SELECT COUNT(`warning_id`) > 0 FROM `msz_user_warnings` WHERE `warning_type` IN (%s) AND `user_id` = :user AND `warning_duration` IS NOT NULL AND `warning_duration` >= NOW() ', implode(',', MSZ_WARN_TYPES_HAS_DURATION) )); $checkAddress->bindValue('user', $userId); return $GLOBALS[MSZ_WARN_RESTRICTION_CACHE][$userId] = (bool)($checkAddress->execute() ? $checkAddress->fetchColumn() : false); }