2023-07-26 18:19:46 +00:00
< ? 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 ];
2023-07-27 23:26:05 +00:00
elseif ( empty ( $banInfos ))
return ;
2023-07-26 18:19:46 +00:00
$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 ();
}
}