216 lines
7.5 KiB
PHP
216 lines
7.5 KiB
PHP
<?php
|
|
namespace Misuzu\Emoticons;
|
|
|
|
use InvalidArgumentException;
|
|
use RuntimeException;
|
|
use Index\Data\DbStatementCache;
|
|
use Index\Data\IDbConnection;
|
|
|
|
class Emotes {
|
|
private const EMOTE_ORDER = [
|
|
'order' => 'emote_order',
|
|
'id' => 'emote_id',
|
|
'rank' => 'emote_hierarchy',
|
|
];
|
|
|
|
private IDbConnection $dbConn;
|
|
private DbStatementCache $cache;
|
|
|
|
public function __construct(IDbConnection $dbConn) {
|
|
$this->dbConn = $dbConn;
|
|
$this->cache = new DbStatementCache($dbConn);
|
|
}
|
|
|
|
public function getEmote(string $emoteId): EmoteInfo {
|
|
$stmt = $this->cache->get('SELECT emote_id, emote_order, emote_hierarchy, emote_url FROM msz_emoticons WHERE emote_id = ?');
|
|
$stmt->addParameter(1, $emoteId);
|
|
$stmt->execute();
|
|
|
|
$result = $stmt->getResult();
|
|
|
|
if(!$result->next())
|
|
throw new RuntimeException('No emoticon with that ID exists.');
|
|
|
|
return EmoteInfo::fromResult($result);
|
|
}
|
|
|
|
public static function emoteOrderOptions(): array {
|
|
return array_keys(self::EMOTE_ORDER);
|
|
}
|
|
|
|
// TODO: pagination
|
|
public function getEmotes(
|
|
?int $minRank = null,
|
|
?string $orderBy = null,
|
|
?bool $reverse = null
|
|
): iterable {
|
|
$hasMinRank = $minRank !== null;
|
|
$hasOrderBy = $orderBy !== null;
|
|
$hasReverse = $reverse !== null;
|
|
|
|
$query = 'SELECT emote_id, emote_order, emote_hierarchy, emote_url FROM msz_emoticons';
|
|
if($hasMinRank)
|
|
$query .= ' WHERE emote_hierarchy <= ?';
|
|
if($hasOrderBy) {
|
|
if(!array_key_exists($orderBy, self::EMOTE_ORDER))
|
|
throw new InvalidArgumentException('Invalid $orderBy specified.');
|
|
|
|
$query .= sprintf(' ORDER BY %s', self::EMOTE_ORDER[$orderBy]);
|
|
if($hasReverse)
|
|
$query .= $reverse ? ' DESC' : ' ASC';
|
|
}
|
|
|
|
$stmt = $this->cache->get($query);
|
|
if($hasMinRank)
|
|
$stmt->addParameter(1, $minRank);
|
|
$stmt->execute();
|
|
|
|
return $stmt->getResult()->getIterator(EmoteInfo::fromResult(...));
|
|
}
|
|
|
|
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;
|
|
|
|
$stmt = $this->cache->get('SELECT COUNT(*) FROM msz_emoticons WHERE emote_url = ?');
|
|
$stmt->addParameter(1, $url);
|
|
$stmt->execute();
|
|
$result = $stmt->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);
|
|
|
|
$stmt = $this->cache->get('INSERT INTO msz_emoticons (emote_url, emote_hierarchy, emote_order) SELECT ?, ?, COALESCE(?, (SELECT FLOOR(MAX(emote_order) / 10) * 10 + 10 FROM msz_emoticons), 10)');
|
|
$stmt->addParameter(1, $url);
|
|
$stmt->addParameter(2, $minRank);
|
|
$stmt->addParameter(3, $order);
|
|
$stmt->execute();
|
|
|
|
return $this->getEmote((string)$this->dbConn->getLastInsertId());
|
|
}
|
|
|
|
public function deleteEmote(EmoteInfo|string $infoOrId): void {
|
|
if($infoOrId instanceof EmoteInfo)
|
|
$infoOrId = $infoOrId->getId();
|
|
|
|
$stmt = $this->cache->get('DELETE FROM msz_emoticons WHERE emote_id = ?');
|
|
$stmt->addParameter(1, $infoOrId);
|
|
$stmt->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();
|
|
|
|
$stmt = $this->cache->get('UPDATE msz_emoticons SET emote_order = COALESCE(?, emote_order), emote_hierarchy = COALESCE(?, emote_hierarchy), emote_url = COALESCE(?, emote_url) WHERE emote_id = ?');
|
|
$stmt->addParameter(1, $order);
|
|
$stmt->addParameter(2, $minRank);
|
|
$stmt->addParameter(3, $url);
|
|
$stmt->addParameter(4, $infoOrId);
|
|
$stmt->execute();
|
|
}
|
|
|
|
public function updateEmoteOrderOffset(EmoteInfo|string $infoOrId, int $offset): void {
|
|
if($offset === 0) return;
|
|
if($infoOrId instanceof EmoteInfo)
|
|
$infoOrId = $infoOrId->getId();
|
|
|
|
$stmt = $this->cache->get('UPDATE msz_emoticons SET emote_order = emote_order + ? WHERE emote_id = ?');
|
|
$stmt->addParameter(1, $offset);
|
|
$stmt->addParameter(2, $infoOrId);
|
|
$stmt->execute();
|
|
}
|
|
|
|
public function getEmoteStrings(EmoteInfo|string $infoOrId): iterable {
|
|
if($infoOrId instanceof EmoteInfo)
|
|
$infoOrId = $infoOrId->getId();
|
|
|
|
$stmt = $this->cache->get('SELECT emote_id, emote_string_order, emote_string FROM msz_emoticons_strings WHERE emote_id = ? ORDER BY emote_string_order');
|
|
$stmt->addParameter(1, $infoOrId);
|
|
$stmt->execute();
|
|
|
|
return $stmt->getResult()->getIterator(EmoteStringInfo::fromResult(...));
|
|
}
|
|
|
|
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;
|
|
|
|
$stmt = $this->cache->get('SELECT COUNT(*) FROM msz_emoticons_strings WHERE emote_string = ?');
|
|
$stmt->addParameter(1, $string);
|
|
$stmt->execute();
|
|
$result = $stmt->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();
|
|
|
|
$stmt = $this->cache->get('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)');
|
|
$stmt->addParameter(1, $infoOrId);
|
|
$stmt->addParameter(2, $string);
|
|
$stmt->addParameter(3, $order);
|
|
$stmt->execute();
|
|
}
|
|
|
|
public function removeEmoteString(EmoteStringInfo|string $infoOrString): void {
|
|
if($infoOrString instanceof EmoteStringInfo)
|
|
$infoOrString = $infoOrString->getString();
|
|
|
|
$stmt = $this->cache->get('DELETE FROM msz_emoticons_strings WHERE emote_string = ?');
|
|
$stmt->addParameter(1, $infoOrString);
|
|
$stmt->execute();
|
|
}
|
|
}
|