misuzu/src/Emoticons/Emotes.php
flash 3909cdf762 Rewrote backend for emoticons.
Manage actually works this time!!!
2023-07-12 21:52:55 +00:00

275 lines
9.9 KiB
PHP

<?php
namespace Misuzu\Emoticons;
use RuntimeException;
use Index\Data\IDbConnection;
use Index\Data\IDbStatement;
class Emotes {
private const EMOTE_ORDER = [
'order' => 'emote_order',
'id' => 'emote_id',
'rank' => 'emote_hierarchy',
];
private IDbConnection $dbConn;
private ?IDbStatement $getEmoteById = null;
private ?IDbStatement $checkEmoteUrl = null;
private ?IDbStatement $createEmote = null;
private ?IDbStatement $deleteEmote = null;
private ?IDbStatement $updateEmote = null;
private ?IDbStatement $updateEmoteOrderOffset = null;
private ?IDbStatement $getEmoteStrings = null;
private ?IDbStatement $checkEmoteString = null;
private ?IDbStatement $addEmoteString = null;
private ?IDbStatement $removeEmoteString = null;
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
}
public function getEmoteById(string $emoteId, bool $withStrings = false): EmoteInfo {
if($this->getEmoteById === null)
$this->getEmoteById = $this->dbConn->prepare(
'SELECT emote_id, emote_order, emote_hierarchy, emote_url FROM msz_emoticons WHERE emote_id = ?');
else
$this->getEmoteById->reset();
$this->getEmoteById->addParameter(1, $emoteId);
$this->getEmoteById->execute();
$result = $this->getEmoteById->getResult();
if(!$result->next())
throw new RuntimeException('No emoticon with ID exists.');
$strings = $withStrings ? $this->getEmoteStrings($emoteId) : [];
return new EmoteInfo($result, $strings);
}
public static function emoteOrderOptions(): array {
return array_keys(self::EMOTE_ORDER);
}
// TODO: pagination
public function getAllEmotes(
int $minRank = -1,
string $orderBy = '',
bool $desc = false,
bool $withStrings = false
): array {
if($minRank < 0) $minRank = PHP_INT_MAX;
$orderBy = self::EMOTE_ORDER[$orderBy] ?? self::EMOTE_ORDER[array_key_first(self::EMOTE_ORDER)];
$getAll = $this->dbConn->prepare(sprintf(
'SELECT emote_id, emote_order, emote_hierarchy, emote_url FROM msz_emoticons WHERE emote_hierarchy <= ? ORDER BY %s %s',
$orderBy, ($desc ? 'DESC' : 'ASC')
));
$getAll->addParameter(1, $minRank);
$getAll->execute();
$emotes = [];
$result = $getAll->getResult();
if($withStrings) {
while($result->next())
$emotes[] = new EmoteInfo($result, $this->getEmoteStrings((string)$result->getInteger(0)));
} else {
while($result->next())
$emotes[] = new EmoteInfo($result);
}
return $emotes;
}
private static function checkEmoteUrlInternal(string $url): string {
// more checks?
if(empty($url))
return 'empty';
if(trim($url) !== $url)
return 'spaces';
return '';
}
public function checkEmoteUrl(string $url): string {
$check = self::checkEmoteUrlInternal($url);
if($check !== '')
return $check;
if($this->checkEmoteUrl === null)
$this->checkEmoteUrl = $this->dbConn->prepare('SELECT COUNT(*) FROM msz_emoticons WHERE emote_url = ?');
else
$this->checkEmoteUrl->reset();
$this->checkEmoteUrl->addParameter(1, $url);
$this->checkEmoteUrl->execute();
$result = $this->checkEmoteUrl->getResult();
if($result->next() && $result->getInteger(0) > 0)
return 'used';
return '';
}
public function createEmote(string $url, int $minRank = 0, ?int $order = null): EmoteInfo {
$check = self::checkEmoteUrlInternal($url);
if($check !== '')
throw new InvalidArgumentException('$url is not correctly formatted: ' . $check);
if($this->createEmote === null)
$this->createEmote = $this->dbConn->prepare('INSERT INTO msz_emoticons (emote_url, emote_hierarchy, emote_order) SELECT ?, ?, COALESCE(?, (SELECT FLOOR(MAX(emote_order) / 10) * 10 + 10 FROM msz_emoticons), 10)');
else
$this->createEmote->reset();
$this->createEmote->addParameter(1, $url);
$this->createEmote->addParameter(2, $minRank);
$this->createEmote->addParameter(3, $order);
$this->createEmote->execute();
return $this->getEmoteById((string)$this->dbConn->getLastInsertId());
}
public function deleteEmote(EmoteInfo|string $infoOrId): void {
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->deleteEmote === null)
$this->deleteEmote = $this->dbConn->prepare('DELETE FROM msz_emoticons WHERE emote_id = ?');
else
$this->deleteEmote->reset();
$this->deleteEmote->addParameter(1, $infoOrId);
$this->deleteEmote->execute();
}
public function updateEmote(
EmoteInfo|string $infoOrId,
?int $order = null,
?int $minRank = null,
?string $url = null
): void {
if($url !== null) {
$check = self::checkEmoteUrlInternal($url);
if($check !== '')
throw new InvalidArgumentException('$url is not correctly formatted: ' . $check);
}
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->updateEmote === null)
$this->updateEmote = $this->dbConn->prepare(
'UPDATE msz_emoticons SET emote_order = COALESCE(?, emote_order), emote_hierarchy = COALESCE(?, emote_hierarchy), emote_url = COALESCE(?, emote_url) WHERE emote_id = ?');
else
$this->updateEmote->reset();
$this->updateEmote->addParameter(1, $order);
$this->updateEmote->addParameter(2, $minRank);
$this->updateEmote->addParameter(3, $url);
$this->updateEmote->addParameter(4, $infoOrId);
$this->updateEmote->execute();
}
public function updateEmoteOrderOffset(EmoteInfo|string $infoOrId, int $offset): void {
if($offset === 0) return;
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->updateEmoteOrderOffset === null)
$this->updateEmoteOrderOffset = $this->dbConn->prepare('UPDATE msz_emoticons SET emote_order = emote_order + ? WHERE emote_id = ?');
else
$this->updateEmoteOrderOffset->reset();
$this->updateEmoteOrderOffset->addParameter(1, $offset);
$this->updateEmoteOrderOffset->addParameter(2, $infoOrId);
$this->updateEmoteOrderOffset->execute();
}
public function getEmoteStrings(EmoteInfo|string $infoOrId): array {
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->getEmoteStrings === null)
$this->getEmoteStrings = $this->dbConn->prepare('SELECT emote_id, emote_string_order, emote_string FROM msz_emoticons_strings WHERE emote_id = ? ORDER BY emote_string_order');
else
$this->getEmoteStrings->reset();
$this->getEmoteStrings->addParameter(1, $infoOrId);
$this->getEmoteStrings->execute();
$strings = [];
$result = $this->getEmoteStrings->getResult();
while($result->next())
$strings[] = new EmoteStringInfo($result);
return $strings;
}
private static function checkEmoteStringInternal(string $string): string {
if(empty($string))
return 'empty';
if(trim($string) !== $string)
return 'spaces';
if(strtolower($string) !== $string)
return 'case';
if(!preg_match('#^[a-z][a-z0-9_-]*[a-z0-9]$#', $string))
return 'format';
return '';
}
public function checkEmoteString(string $string): string {
$check = self::checkEmoteStringInternal($string);
if($check !== '')
return $check;
if($this->checkEmoteString === null)
$this->checkEmoteString = $this->dbConn->prepare('SELECT COUNT(*) FROM msz_emoticons_strings WHERE emote_string = ?');
else
$this->checkEmoteString->reset();
$this->checkEmoteString->addParameter(1, $string);
$this->checkEmoteString->execute();
$result = $this->checkEmoteString->getResult();
if($result->next() && $result->getInteger(0) > 0)
return 'used';
return '';
}
public function addEmoteString(EmoteInfo|string $infoOrId, string $string, ?int $order = null): void {
$check = self::checkEmoteStringInternal($string);
if($check !== '')
throw new InvalidArgumentException('$string is not correctly formatted: ' . $check);
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->addEmoteString === null)
$this->addEmoteString = $this->dbConn->prepare('INSERT INTO msz_emoticons_strings (emote_id, emote_string, emote_string_order) SELECT ? AS target_emote_id, ?, COALESCE(?, (SELECT MAX(emote_string_order) + 1 FROM msz_emoticons_strings WHERE emote_id = target_emote_id), 1)');
else
$this->addEmoteString->reset();
$this->addEmoteString->addParameter(1, $infoOrId);
$this->addEmoteString->addParameter(2, $string);
$this->addEmoteString->addParameter(3, $order);
$this->addEmoteString->execute();
}
public function removeEmoteString(EmoteStringInfo|string $infoOrString): void {
if($infoOrString instanceof EmoteStringInfo)
$infoOrString = $infoOrString->getString();
if($this->removeEmoteString === null)
$this->removeEmoteString = $this->dbConn->prepare('DELETE FROM msz_emoticons_strings WHERE emote_string = ?');
else
$this->removeEmoteString->reset();
$this->removeEmoteString->addParameter(1, $infoOrString);
$this->removeEmoteString->execute();
}
}