143 lines
4.4 KiB
PHP
143 lines
4.4 KiB
PHP
<?php
|
|
namespace Misuzu\Logs;
|
|
|
|
use InvalidArgumentException;
|
|
use Index\Db\{DbConnection,DbStatementCache};
|
|
use Misuzu\Pagination;
|
|
use Misuzu\Users\UserInfo;
|
|
|
|
class LogsData {
|
|
private DbStatementCache $cache;
|
|
|
|
public function __construct(DbConnection $dbConn) {
|
|
$this->cache = new DbStatementCache($dbConn);
|
|
}
|
|
|
|
public function countLogs(
|
|
UserInfo|string|null $userInfo = null,
|
|
string|null|false $remoteAddress = false,
|
|
): int {
|
|
if($userInfo instanceof UserInfo)
|
|
$userInfo = $userInfo->id;
|
|
|
|
$hasUserInfo = $userInfo !== null;
|
|
$hasRemoteAddr = $remoteAddress !== false;
|
|
|
|
$args = 0;
|
|
$query = 'SELECT COUNT(*) FROM msz_audit_log';
|
|
if($hasUserInfo) {
|
|
++$args;
|
|
$query .= ' WHERE user_id = ?';
|
|
}
|
|
if($remoteAddress !== false)
|
|
$query .= sprintf(
|
|
' %s log_remote_addr %s',
|
|
++$args > 1 ? ' AND' : ' WHERE',
|
|
$remoteAddress === null ? 'IS NULL' : '= INET6_ATON(?)'
|
|
);
|
|
|
|
$stmt = $this->cache->get($query);
|
|
|
|
if($hasUserInfo)
|
|
$stmt->nextParameter($userInfo);
|
|
if(is_string($remoteAddress))
|
|
$stmt->nextParameter($remoteAddress);
|
|
|
|
$stmt->execute();
|
|
$result = $stmt->getResult();
|
|
$count = 0;
|
|
|
|
if($result->next())
|
|
$count = $result->getInteger(0);
|
|
|
|
return $count;
|
|
}
|
|
|
|
/** @return \Iterator<int, LogInfo> */
|
|
public function getLogs(
|
|
UserInfo|string|null $userInfo = null,
|
|
string|null|false $remoteAddress = false,
|
|
?Pagination $pagination = null
|
|
): iterable {
|
|
if($userInfo instanceof UserInfo)
|
|
$userInfo = $userInfo->id;
|
|
|
|
$hasUserInfo = $userInfo !== null;
|
|
$hasPagination = $pagination !== null;
|
|
|
|
$args = 0;
|
|
$query = <<<SQL
|
|
SELECT log_id, user_id, log_action, log_params,
|
|
UNIX_TIMESTAMP(log_created),
|
|
INET6_NTOA(log_remote_addr),
|
|
log_country
|
|
FROM msz_audit_log
|
|
SQL;
|
|
if($hasUserInfo) {
|
|
++$args;
|
|
$query .= ' WHERE user_id = ?';
|
|
}
|
|
if($remoteAddress !== false)
|
|
$query .= sprintf(
|
|
' %s log_remote_addr %s',
|
|
++$args > 1 ? ' AND' : ' WHERE',
|
|
$remoteAddress === null ? 'IS NULL' : '= INET6_ATON(?)'
|
|
);
|
|
$query .= ' ORDER BY log_created DESC';
|
|
if($hasPagination)
|
|
$query .= ' LIMIT ? OFFSET ?';
|
|
|
|
$stmt = $this->cache->get($query);
|
|
|
|
if($hasUserInfo)
|
|
$stmt->nextParameter($userInfo);
|
|
if(is_string($remoteAddress))
|
|
$stmt->nextParameter($remoteAddress);
|
|
if($hasPagination)
|
|
$pagination->addToStatement($stmt);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->getResultIterator(LogInfo::fromResult(...));
|
|
}
|
|
|
|
/** @param mixed[] $params */
|
|
public function createLog(
|
|
UserInfo|string|null $userInfo,
|
|
string $action,
|
|
array $params = [],
|
|
?string $remoteAddress = null,
|
|
string $countryCode = 'XX',
|
|
): string {
|
|
if($userInfo instanceof UserInfo)
|
|
$userInfo = $userInfo->id;
|
|
|
|
// action names should have stricter validation,
|
|
// i do want to switch to a lowercase colon separated format later but i'll save that for the unified log in Hanyuu
|
|
$actionTrim = trim($action);
|
|
if($actionTrim !== $action || empty($actionTrim))
|
|
throw new InvalidArgumentException('$action may not be empty.');
|
|
|
|
if(strlen($countryCode) !== 2 || !ctype_alpha($countryCode))
|
|
throw new InvalidArgumentException('$countryCode must be two alpha characters.');
|
|
|
|
foreach($params as &$param) {
|
|
if(is_array($param))
|
|
$param = implode(', ', $param);
|
|
elseif(is_object($param))
|
|
$param = (string)$param;
|
|
}
|
|
|
|
$params = json_encode($params);
|
|
|
|
$stmt = $this->cache->get('INSERT INTO msz_audit_log (user_id, log_action, log_params, log_remote_addr, log_country) VALUES (?, ?, ?, INET6_ATON(?), UPPER(?))');
|
|
$stmt->nextParameter($userInfo);
|
|
$stmt->nextParameter($action);
|
|
$stmt->nextParameter($params);
|
|
$stmt->nextParameter($remoteAddress);
|
|
$stmt->nextParameter($countryCode);
|
|
$stmt->execute();
|
|
|
|
return (string)$stmt->lastInsertId;
|
|
}
|
|
}
|