Rewrote backend for emoticons.

Manage actually works this time!!!
This commit is contained in:
flash 2023-07-12 21:52:55 +00:00
parent 9b65ce005a
commit 3909cdf762
10 changed files with 499 additions and 235 deletions

View file

@ -1,6 +1,7 @@
<?php <?php
namespace Misuzu; namespace Misuzu;
use RuntimeException;
use Misuzu\Users\User; use Misuzu\Users\User;
require_once '../../../misuzu.php'; require_once '../../../misuzu.php';
@ -10,43 +11,106 @@ if(!User::hasCurrent() || !perms_check_user(MSZ_PERMS_GENERAL, User::getCurrent(
return; return;
} }
$emoteId = !empty($_GET['e']) && is_string($_GET['e']) ? (int)$_GET['e'] : 0; $emotes = $msz->getEmotes();
$isNew = $emoteId <= 0; $emoteId = (string)filter_input(INPUT_GET, 'e', FILTER_SANITIZE_NUMBER_INT);
$emoteInfo = !$isNew ? Emoticon::byId($emoteId) : new Emoticon; $loadEmoteInfo = fn() => $emotes->getEmoteById($emoteId, true);
if(CSRF::validateRequest() && isset($_POST['emote_order']) && isset($_POST['emote_hierarchy']) && !empty($_POST['emote_url']) && !empty($_POST['emote_strings'])) { if(empty($emoteId))
$emoteInfo->setUrl($_POST['emote_url']) $isNew = true;
->setRank($_POST['emote_hierarchy']) else
->setOrder($_POST['emote_order']) try {
->save(); $isNew = false;
$emoteInfo = $loadEmoteInfo();
} catch(RuntimeException $ex) {
echo render_error(404);
return;
}
if($isNew && !$emoteInfo->hasId()) // make errors not echos lol
throw new \Exception("SOMETHING HAPPENED"); while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$order = (int)filter_input(INPUT_POST, 'em_order', FILTER_SANITIZE_NUMBER_INT);
$minRank = (int)filter_input(INPUT_POST, 'em_minrank', FILTER_SANITIZE_NUMBER_INT);
$url = trim((string)filter_input(INPUT_POST, 'em_url'));
$strings = explode(' ', trim((string)filter_input(INPUT_POST, 'em_strings')));
$setStrings = array_column($emoteInfo->getStrings(), 'emote_string'); if($isNew || $url !== $emoteInfo->getUrl()) {
$applyStrings = explode(' ', mb_strtolower($_POST['emote_strings'])); $checkUrl = $emotes->checkEmoteUrl($url);
$removeStrings = []; if($checkUrl !== '') {
echo match($checkUrl) {
foreach($setStrings as $string) { 'empty' => 'URL may not be empty.',
if(!in_array($string, $applyStrings)) { 'spaces' => 'URL may not end or start with spaces.',
$removeStrings[] = $string; 'used' => 'This URL already belongs to another emoticon.',
default => 'URL cannot be accepted: ' . $checkUrl,
};
break;
} }
} }
$setStrings = array_diff($setStrings, $removeStrings); if($order == 0)
$order = null;
foreach($applyStrings as $string) { $reload = false;
if(!in_array($string, $setStrings)) { if($isNew) {
$setStrings[] = $string; $emoteInfo = $emotes->createEmote($url, $minRank, $order);
} else {
if($order === $emoteInfo->getOrder())
$order = null;
if($minRank === $emoteInfo->getMinRank())
$minRank = null;
if($url === $emoteInfo->getUrl())
$url = null;
if($order !== null || $minRank !== null || $url !== null) {
$reload = true;
$emotes->updateEmote($emoteInfo, $order, $minRank, $url);
} }
} }
foreach($removeStrings as $string) $sCurrent = $emoteInfo->getStringsRaw();
$emoteInfo->removeString($string); $sApply = $strings;
foreach($setStrings as $string) $sRemove = [];
$emoteInfo->addString($string);
foreach($sCurrent as $string)
if(!in_array($string, $sApply)) {
$sRemove[] = $string;
$emotes->removeEmoteString($string);
}
$sCurrent = array_diff($sCurrent, $sRemove);
if(!$reload)
$reload = !empty($sRemove) || !empty(array_diff($sApply, $sCurrent));
foreach($sApply as $string)
if(!in_array($string, $sCurrent)) {
$checkString = $emotes->checkEmoteString($string);
if($checkString === '') {
$emotes->addEmoteString($emoteInfo, $string);
} else {
echo match($checkString) {
'empty' => 'String may not be empty.',
'spaces' => 'String may not end or start with spaces.',
'case' => 'String must be lowercase.',
'format' => 'String must follow proper formatting.',
'used' => 'This string has already been used for another emoticon.',
default => 'String cannot be accepted: ' . $checkString,
};
break;
}
$sCurrent[] = $string;
}
if($reload) {
if($isNew)
url_redirect('manage-general-emoticon', ['emote' => $emoteInfo->getId()]);
else
$emoteInfo = $loadEmoteInfo();
}
break;
} }
Template::render('manage.general.emoticon', [ Template::render('manage.general.emoticon', [
'emote_info' => $emoteInfo, 'emote_new' => $isNew,
'emote_info' => $emoteInfo ?? null,
]); ]);

View file

@ -1,6 +1,7 @@
<?php <?php
namespace Misuzu; namespace Misuzu;
use RuntimeException;
use Misuzu\Users\User; use Misuzu\Users\User;
require_once '../../../misuzu.php'; require_once '../../../misuzu.php';
@ -10,22 +11,32 @@ if(!User::hasCurrent() || !perms_check_user(MSZ_PERMS_GENERAL, User::getCurrent(
return; return;
} }
if(CSRF::validateRequest() && !empty($_GET['emote']) && is_string($_GET['emote'])) { $emotes = $msz->getEmotes();
$emoteId = (int)$_GET['emote'];
$emoteInfo = Emoticon::byId($emoteId);
if(empty($emoteInfo)) { if(CSRF::validateRequest() && !empty($_GET['emote'])) {
$emoteId = (string)filter_input(INPUT_GET, 'emote', FILTER_SANITIZE_NUMBER_INT);
try {
$emoteInfo = $emotes->getEmoteById($emoteId);
} catch(RuntimeException $ex) {
echo render_error(404); echo render_error(404);
return; return;
} }
if(!empty($_GET['order']) && is_string($_GET['order'])) { if(!empty($_GET['delete'])) {
$emoteInfo->changeOrder($_GET['order'] === 'i' ? 1 : -1); $emotes->deleteEmote($emoteInfo);
} elseif(!empty($_GET['alias']) && is_string($_GET['alias']) && ctype_alnum($_GET['alias'])) { } else {
$emoteInfo->addString(mb_strtolower($_GET['alias'])); if(isset($_GET['order'])) {
return; $order = filter_input(INPUT_GET, 'order');
} elseif(!empty($_GET['delete'])) { $offset = $order === 'i' ? 1 : ($order === 'd' ? -1 : 0);
$emoteInfo->delete(); $emotes->updateEmoteOrderOffset($emoteInfo, $offset);
}
if(isset($_GET['alias'])) {
$alias = (string)filter_input(INPUT_GET, 'alias');
if($emotes->checkEmoteString($alias) === '')
$emotes->addEmoteString($emoteInfo, $alias);
}
} }
url_redirect('manage-general-emoticons'); url_redirect('manage-general-emoticons');
@ -33,5 +44,5 @@ if(CSRF::validateRequest() && !empty($_GET['emote']) && is_string($_GET['emote']
} }
Template::render('manage.general.emoticons', [ Template::render('manage.general.emoticons', [
'emotes' => Emoticon::all(PHP_INT_MAX), 'emotes' => $emotes->getAllEmotes(),
]); ]);

View file

@ -1,179 +0,0 @@
<?php
namespace Misuzu;
use InvalidArgumentException;
final class Emoticon {
private int $emote_id;
private int $emote_order;
private int $emote_hierarchy;
private string $emote_url;
public const ALL = PHP_INT_MAX;
public function __construct() {
}
public function getId(): int {
return $this->emote_id ?? 0;
}
public function hasId(): bool {
return isset($this->emote_id) && $this->emote_id > 0;
}
public function getOrder(): int {
return $this->emote_order ?? 0;
}
public function setOrder(int $order): self {
$this->emote_order = $order;
return $this;
}
public function changeOrder(int $difference): self {
if(!$this->hasId())
return $this;
DB::prepare('
UPDATE `msz_emoticons`
SET `emote_order` = `emote_order` + :diff
WHERE `emote_id` = :id
')->bind('id', $this->getId())
->bind('diff', $difference)
->execute();
return $this;
}
public function getRank(): int {
return $this->emote_hierarchy ?? 0;
}
public function setRank(int $rank): self {
$this->emote_hierarchy = $rank;
return $this;
}
public function getUrl(): string {
return $this->emote_url ?? '';
}
public function setUrl(string $url): self {
$this->emote_url = $url;
return $this;
}
public function addString(string $string, ?int $order = null): bool {
if(!$this->hasId())
return false;
if($order === null) {
$order = DB::prepare('
SELECT MAX(`emote_string_order`) + 1
FROM `msz_emoticons_strings`
WHERE `emote_id` = :id
')->bind('id', $this->getId())->fetchColumn();
}
return DB::prepare('
REPLACE INTO `msz_emoticons_strings` (`emote_id`, `emote_string_order`, `emote_string`)
VALUES (:id, :order, :string)
')->bind('id', $this->getId())
->bind('order', $order)
->bind('string', $string)
->execute();
}
public function removeString(string $string): bool {
if(!$this->hasId())
return false;
return DB::prepare('
DELETE FROM `msz_emoticons_strings`
WHERE `emote_string` = :string
')->bind('string', $string)
->execute();
}
public function getStrings(): array {
if(!$this->hasId())
return [];
return DB::prepare('
SELECT `emote_string_order`, `emote_string`
FROM `msz_emoticons_strings`
WHERE `emote_id` = :id
ORDER BY `emote_string_order`
')->bind('id', $this->getId())->fetchObjects();
}
public function save(): bool {
if($this->hasId()) {
$save = DB::prepare('
UPDATE `msz_emoticons`
SET `emote_order` = :order,
`emote_hierarchy` = :hierarchy,
`emote_url` = :url
WHERE `emote_id` = :id
')->bind('id', $this->getId());
} else {
$save = DB::prepare('
INSERT INTO `msz_emoticons` (`emote_order`, `emote_hierarchy`, `emote_url`)
VALUES (:order, :hierarchy, :url)
');
}
$saved = $save->bind('order', $this->getOrder())
->bind('hierarchy', $this->getRank())
->bind('url', $this->getUrl())
->execute();
if(!$this->hasId() && $saved)
$this->emote_id = DB::lastId();
return $saved;
}
public function delete(): void {
if(!$this->hasId())
return;
DB::prepare('DELETE FROM `msz_emoticons` WHERE `emote_id` = :id')
->bind('id', $this->getId())
->execute();
}
public static function byId(int $emoteId): self {
if($emoteId < 1)
throw new InvalidArgumentException('$emoteId is not a valid emoticon id.');
$getEmote = DB::prepare('
SELECT `emote_id`, `emote_order`, `emote_hierarchy`, `emote_url`
FROM `msz_emoticons`
WHERE `emote_id` = :id
');
$getEmote->bind('id', $emoteId);
return $getEmote->fetchObject(self::class);
}
public static function all(int $hierarchy = self::ALL, bool $unique = false, bool $order = true): array {
$getEmotes = DB::prepare('
SELECT `emote_id`, `emote_order`, `emote_hierarchy`, `emote_url`
FROM `msz_emoticons`
WHERE `emote_hierarchy` <= :hierarchy
ORDER BY IF(:order, `emote_order`, `emote_id`)
');
$getEmotes->bind('hierarchy', $hierarchy);
$getEmotes->bind('order', $order);
$emotes = $getEmotes->fetchObjects(self::class);
// Removes aliases, emote with lowest ordering is considered the main
if($unique) {
$existing = [];
for($i = 0; $i < count($emotes); $i++) {
if(in_array($emotes[$i]->emote_url, $existing)) {
unset($emotes[$i]);
} else {
$existing[] = $emotes[$i]->emote_url;
}
}
}
return $emotes;
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace Misuzu\Emoticons;
use Stringable;
use Index\Data\IDbResult;
class EmoteInfo implements Stringable {
private string $id;
private int $order;
private int $rank;
private string $url;
private array $strings;
public function __construct(IDbResult $result, array $strings = []) {
$this->id = (string)$result->getInteger(0);
$this->order = $result->getInteger(1);
$this->rank = $result->getInteger(2);
$this->url = $result->getString(3);
$this->strings = $strings;
}
public function getId(): string {
return $this->id;
}
public function getOrder(): int {
return $this->order;
}
public function getMinRank(): int {
return $this->rank;
}
public function getUrl(): string {
return $this->url;
}
public function getStrings(): array {
return $this->strings;
}
public function getStringsRaw(): array {
$strings = [];
foreach($this->strings as $info)
$strings[] = $info->getString();
return $strings;
}
public function __toString(): string {
return $this->url;
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace Misuzu\Emoticons;
use Stringable;
use Index\Data\IDbResult;
class EmoteStringInfo implements Stringable {
private string $emoteId;
private int $order;
private string $string;
public function __construct(IDbResult $result) {
$this->emoteId = (string)$result->getInteger(0);
$this->order = $result->getInteger(1);
$this->string = $result->getString(2);
}
public function getEmoteId(): string {
return $this->emoteId;
}
public function getOrder(): int {
return $this->order;
}
public function getString(): string {
return $this->string;
}
public function __toString(): string {
return $this->string;
}
}

274
src/Emoticons/Emotes.php Normal file
View file

@ -0,0 +1,274 @@
<?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();
}
}

View file

@ -3,6 +3,7 @@ namespace Misuzu;
use Misuzu\Template; use Misuzu\Template;
use Misuzu\Config\IConfig; use Misuzu\Config\IConfig;
use Misuzu\Emoticons\Emotes;
use Misuzu\SharpChat\SharpChatRoutes; use Misuzu\SharpChat\SharpChatRoutes;
use Misuzu\Users\Users; use Misuzu\Users\Users;
use Index\Data\IDbConnection; use Index\Data\IDbConnection;
@ -21,11 +22,13 @@ class MisuzuContext {
private IConfig $config; private IConfig $config;
private Users $users; private Users $users;
private HttpFx $router; private HttpFx $router;
private Emotes $emotes;
public function __construct(IDbConnection $dbConn, IConfig $config) { public function __construct(IDbConnection $dbConn, IConfig $config) {
$this->dbConn = $dbConn; $this->dbConn = $dbConn;
$this->config = $config; $this->config = $config;
$this->users = new Users($this->dbConn); $this->users = new Users($this->dbConn);
$this->emotes = new Emotes($this->dbConn);
} }
public function getDbConn(): IDbConnection { public function getDbConn(): IDbConnection {
@ -57,6 +60,10 @@ class MisuzuContext {
return $this->users; return $this->users;
}*/ }*/
public function getEmotes(): Emotes {
return $this->emotes;
}
public function setUpHttp(bool $legacy = false): void { public function setUpHttp(bool $legacy = false): void {
$this->router = new HttpFx; $this->router = new HttpFx;
$this->router->use('/', function($response) { $this->router->use('/', function($response) {
@ -125,7 +132,7 @@ class MisuzuContext {
$this->router->get('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadGET')); $this->router->get('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadGET'));
$this->router->post('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadPOST')); $this->router->post('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadPOST'));
new SharpChatRoutes($this->router, $this->config->scopeTo('sockChat')); new SharpChatRoutes($this->router, $this->config->scopeTo('sockChat'), $this->emotes);
} }
private function registerLegacyRedirects(): void { private function registerLegacyRedirects(): void {

View file

@ -3,11 +3,11 @@ namespace Misuzu\SharpChat;
use Index\Colour\Colour; use Index\Colour\Colour;
use Index\Routing\IRouter; use Index\Routing\IRouter;
use Misuzu\AuthToken;
use Misuzu\Config\IConfig; use Misuzu\Config\IConfig;
use Misuzu\Emoticons\Emotes;
// Replace // Replace
use Misuzu\AuthToken;
use Misuzu\Emoticon;
use Misuzu\Users\User; use Misuzu\Users\User;
use Misuzu\Users\UserSession; use Misuzu\Users\UserSession;
use Misuzu\Users\UserWarning; use Misuzu\Users\UserWarning;
@ -17,10 +17,12 @@ use Misuzu\Users\UserSessionNotFoundException;
final class SharpChatRoutes { final class SharpChatRoutes {
private IConfig $config; private IConfig $config;
private Emotes $emotes;
private string $hashKey = 'woomy'; private string $hashKey = 'woomy';
public function __construct(IRouter $router, IConfig $config) { public function __construct(IRouter $router, IConfig $config, Emotes $emotes) {
$this->config = $config; $this->config = $config;
$this->emotes = $emotes;
$hashKey = $this->config->getValue('hashKey', IConfig::T_STR, ''); $hashKey = $this->config->getValue('hashKey', IConfig::T_STR, '');
@ -68,23 +70,23 @@ final class SharpChatRoutes {
$router->delete('/_sockchat/bans/revoke', [$this, 'deleteBanRevoke']); $router->delete('/_sockchat/bans/revoke', [$this, 'deleteBanRevoke']);
} }
public static function getEmotes($response, $request): array { public function getEmotes($response, $request): array {
$response->setHeader('Access-Control-Allow-Origin', '*'); $response->setHeader('Access-Control-Allow-Origin', '*');
$response->setHeader('Access-Control-Allow-Methods', 'GET'); $response->setHeader('Access-Control-Allow-Methods', 'GET');
$raw = Emoticon::all(); $emotes = $this->emotes->getAllEmotes(withStrings: true);
$out = []; $out = [];
foreach($raw as $emote) { foreach($emotes as $emoteInfo) {
$strings = []; $strings = [];
foreach($emote->getStrings() as $string) foreach($emoteInfo->getStrings() as $stringInfo)
$strings[] = sprintf(':%s:', $string->emote_string); $strings[] = sprintf(':%s:', $stringInfo->getString());
$out[] = [ $out[] = [
'Text' => $strings, 'Text' => $strings,
'Image' => $emote->getUrl(), 'Image' => $emoteInfo->getUrl(),
'Hierarchy' => $emote->getRank(), 'Hierarchy' => $emoteInfo->getMinRank(),
]; ];
} }

View file

@ -2,7 +2,7 @@
{% from 'macros.twig' import container_title %} {% from 'macros.twig' import container_title %}
{% from '_layout/input.twig' import input_csrf, input_text, input_checkbox, input_file, input_select, input_colour %} {% from '_layout/input.twig' import input_csrf, input_text, input_checkbox, input_file, input_select, input_colour %}
{% set title = emote_info is null ? 'Adding a new emoticon' : 'Editing #' ~ emote_info.id %} {% set title = emote_new ? 'Adding a new emoticon' : 'Editing #' ~ emote_info.id %}
{% block manage_content %} {% block manage_content %}
<div class="container manage__emotes"> <div class="container manage__emotes">
@ -13,22 +13,22 @@
<label class="manage__emote__field"> <label class="manage__emote__field">
<div class="manage__emote__field__name">Order</div> <div class="manage__emote__field__name">Order</div>
{{ input_text('emote_order', 'manage__emote__field__value', emote_info.order|default(0), 'number') }} {{ input_text('em_order', 'manage__emote__field__value', emote_info.order|default(0), 'number') }}
</label> </label>
<label class="manage__emote__field"> <label class="manage__emote__field">
<div class="manage__emote__field__name">Hierarchy</div> <div class="manage__emote__field__name">Minimum Rank</div>
{{ input_text('emote_hierarchy', 'manage__emote__field__value', emote_info.rank|default(0), 'number') }} {{ input_text('em_minrank', 'manage__emote__field__value', emote_info.minRank|default(0), 'number') }}
</label> </label>
<label class="manage__emote__field"> <label class="manage__emote__field">
<div class="manage__emote__field__name">URL</div> <div class="manage__emote__field__name">URL</div>
{{ input_text('emote_url', 'manage__emote__field__value', emote_info.url|default(), 'text', '', true) }} {{ input_text('em_url', 'manage__emote__field__value', emote_info.url|default(), 'text', '', true) }}
</label> </label>
<label class="manage__emote__field"> <label class="manage__emote__field">
<div class="manage__emote__field__name">Strings</div> <div class="manage__emote__field__name">Strings</div>
{{ input_text('emote_strings', 'manage__emote__field__value', emote_info.strings|column('emote_string')|join(' '), 'text', '', true) }} {{ input_text('em_strings', 'manage__emote__field__value', emote_info.strings|default([])|join(' '), 'text', '', true) }}
</label> </label>
<div class="manage__emote__actions"> <div class="manage__emote__actions">

View file

@ -41,7 +41,7 @@
{{ emote.order }} {{ emote.order }}
</div> </div>
<div class="manage__emotes__entry__hierarchy"> <div class="manage__emotes__entry__hierarchy">
{{ emote.rank }} {{ emote.minRank }}
</div> </div>
<div class="manage__emotes__entry__image"> <div class="manage__emotes__entry__image">
<img src="{{ emote.url }}" alt="{{ emote.url }}" class="emoticon manage__emotes__emoticon"> <img src="{{ emote.url }}" alt="{{ emote.url }}" class="emoticon manage__emotes__emoticon">