Clean up emoji model and sidebar. Fix some validation errors. Allow mood to be cleared.
This commit is contained in:
parent
3b8d54460c
commit
427558bd8c
@ -163,7 +163,7 @@ function create_tables(): void {
|
|||||||
)");
|
)");
|
||||||
|
|
||||||
// mood table
|
// mood table
|
||||||
$db->exec("CREATE TABLE IF NOT EXISTS mood (
|
$db->exec("CREATE TABLE IF NOT EXISTS emoji(
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
emoji TEXT UNIQUE NOT NULL,
|
emoji TEXT UNIQUE NOT NULL,
|
||||||
description TEXT NOT NULL
|
description TEXT NOT NULL
|
||||||
@ -185,7 +185,7 @@ function validate_tables(): void {
|
|||||||
$appTables[] = "settings";
|
$appTables[] = "settings";
|
||||||
$appTables[] = "user";
|
$appTables[] = "user";
|
||||||
$appTables[] = "css";
|
$appTables[] = "css";
|
||||||
$appTables[] = "mood";
|
$appTables[] = "emoji";
|
||||||
|
|
||||||
$db = get_db();
|
$db = get_db();
|
||||||
|
|
||||||
|
@ -77,6 +77,10 @@ fieldset.emoji-group {
|
|||||||
gap: 0.3em;
|
gap: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1.site-description {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
.delete-emoji-fieldset .fieldset-items {
|
.delete-emoji-fieldset .fieldset-items {
|
||||||
display: block;
|
display: block;
|
||||||
grid-template-columns: none;
|
grid-template-columns: none;
|
||||||
@ -293,7 +297,7 @@ label.description {
|
|||||||
font-size: 1.0em;
|
font-size: 1.0em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination a {
|
.tick-pagination a {
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
73
src/Controller/EmojiController/EmojiController.php
Normal file
73
src/Controller/EmojiController/EmojiController.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
class EmojiController extends Controller {
|
||||||
|
// Shows the custom emoji management page
|
||||||
|
public function index(){
|
||||||
|
global $config;
|
||||||
|
$emojiList = EmojiModel::loadAll();
|
||||||
|
|
||||||
|
$vars = [
|
||||||
|
'config' => $config,
|
||||||
|
'emojiList' => $emojiList,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->render("emoji.php", $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePost(): void {
|
||||||
|
global $config;
|
||||||
|
|
||||||
|
switch ($_POST['action']) {
|
||||||
|
case 'add':
|
||||||
|
$emoji = trim($_POST['emoji']);
|
||||||
|
$description = trim($_POST['emoji-description']);
|
||||||
|
$this->handleAdd($emoji, $description);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
if (!empty($_POST['delete_emoji_ids'])){
|
||||||
|
$this->handleDelete();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ' . $config->basePath . 'admin/emoji');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleAdd(string $emoji, ?string $description=null): void {
|
||||||
|
// Validate 1 visible character in the emoji
|
||||||
|
if (extension_loaded('mbstring')) {
|
||||||
|
// TODO - log a warning if mbstring isn't loaded
|
||||||
|
$charCount = mb_strlen($emoji, 'UTF-8');
|
||||||
|
if ($charCount !== 1) {
|
||||||
|
// TODO - handle error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the emoji is actually an emoji
|
||||||
|
$emojiPattern = '/^[\x{1F000}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F1E0}-\x{1F1FF}\x{1F900}-\x{1F9FF}\x{1FA70}-\x{1FAFF}]$/u';
|
||||||
|
|
||||||
|
if (!preg_match($emojiPattern, $emoji)) {
|
||||||
|
// TODO - handle error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// emojis should have more bytes than characters
|
||||||
|
$byteCount = strlen($emoji);
|
||||||
|
if ($byteCount <= 1) {
|
||||||
|
// TODO - handle error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It looks like an emoji. Let's add it.
|
||||||
|
EmojiModel::add($emoji, $description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleDelete(): void {
|
||||||
|
$ids = $_POST['delete_emoji_ids'];
|
||||||
|
|
||||||
|
if (!empty($ids)) {
|
||||||
|
EmojiModel::delete($ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,80 +15,8 @@
|
|||||||
$this->render("mood.php", $vars);
|
$this->render("mood.php", $vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shows the custom emoji management page
|
public function handlePost(){
|
||||||
public function showCustomEmoji(){
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
global $config;
|
|
||||||
$emojiList = MoodModel::loadAll();
|
|
||||||
|
|
||||||
$vars = [
|
|
||||||
'config' => $config,
|
|
||||||
'emojiList' => $emojiList,
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->render("emoji.php", $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handlePost(): void {
|
|
||||||
global $config;
|
|
||||||
|
|
||||||
switch ($_POST['action']) {
|
|
||||||
case 'add':
|
|
||||||
$emoji = trim($_POST['emoji']);
|
|
||||||
$description = trim($_POST['emoji-description']);
|
|
||||||
$this->handleAdd($emoji, $description);
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
if (!empty($_POST['delete_emoji_ids'])){
|
|
||||||
$this->handleDelete();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Location: ' . $config->basePath . 'admin/emoji');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handleAdd(string $emoji, ?string $description=null): void {
|
|
||||||
// Validate 1 visible character in the emoji
|
|
||||||
if (extension_loaded('mbstring')) {
|
|
||||||
// TODO - log a warning if mbstring isn't loaded
|
|
||||||
$charCount = mb_strlen($emoji, 'UTF-8');
|
|
||||||
if ($charCount !== 1) {
|
|
||||||
// TODO - handle error
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the emoji is actually an emoji
|
|
||||||
$emojiPattern = '/^[\x{1F000}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F1E0}-\x{1F1FF}\x{1F900}-\x{1F9FF}\x{1FA70}-\x{1FAFF}]$/u';
|
|
||||||
|
|
||||||
if (!preg_match($emojiPattern, $emoji)) {
|
|
||||||
// TODO - handle error
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// emojis should have more bytes than characters
|
|
||||||
$byteCount = strlen($emoji);
|
|
||||||
if ($byteCount <= 1) {
|
|
||||||
// TODO - handle error
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// It looks like an emoji. Let's add it.
|
|
||||||
MoodModel::add($emoji, $description);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handleDelete(): void {
|
|
||||||
$ids = $_POST['delete_emoji_ids'];
|
|
||||||
|
|
||||||
if (!empty($ids)) {
|
|
||||||
$moodModel = new MoodModel();
|
|
||||||
$moodModel->delete($ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handleSetMood(){
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' and isset($_POST['mood'])) {
|
|
||||||
// ensure that the session is valid before proceeding
|
// ensure that the session is valid before proceeding
|
||||||
if (!Session::validateCsrfToken($_POST['csrf_token'])) {
|
if (!Session::validateCsrfToken($_POST['csrf_token'])) {
|
||||||
die('Invalid CSRF token');
|
die('Invalid CSRF token');
|
||||||
@ -97,9 +25,17 @@
|
|||||||
// Get the data we need
|
// Get the data we need
|
||||||
global $config;
|
global $config;
|
||||||
global $user;
|
global $user;
|
||||||
$mood = $_POST['mood'];
|
|
||||||
|
|
||||||
// set the mood
|
switch ($_POST['action']){
|
||||||
|
case 'set':
|
||||||
|
$mood = $_POST['mood'];
|
||||||
|
break;
|
||||||
|
case 'clear':
|
||||||
|
$mood = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set or clear the mood
|
||||||
$user->mood = $mood;
|
$user->mood = $mood;
|
||||||
$user = $user->save();
|
$user = $user->save();
|
||||||
|
|
||||||
@ -110,7 +46,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static function getEmojisWithLabels(): array {
|
private static function getEmojisWithLabels(): array {
|
||||||
$customEmoji = MoodModel::loadAll();
|
$customEmoji = EmojiModel::loadAll();
|
||||||
|
|
||||||
if (!empty($customEmoji)){
|
if (!empty($customEmoji)){
|
||||||
$custom = [];
|
$custom = [];
|
||||||
|
@ -10,15 +10,15 @@ class Router {
|
|||||||
['admin', 'AdminController@handleSave', ['POST']],
|
['admin', 'AdminController@handleSave', ['POST']],
|
||||||
['admin/css', 'CssController'],
|
['admin/css', 'CssController'],
|
||||||
['admin/css', 'CssController@handlePost', ['POST']],
|
['admin/css', 'CssController@handlePost', ['POST']],
|
||||||
['admin/emoji', 'MoodController@showCustomEmoji'],
|
['admin/emoji', 'EmojiController'],
|
||||||
['admin/emoji', 'MoodController@handlePost', ['POST']],
|
['admin/emoji', 'EmojiController@handlePost', ['POST']],
|
||||||
['feed/rss', 'FeedController@rss'],
|
['feed/rss', 'FeedController@rss'],
|
||||||
['feed/atom', 'FeedController@atom'],
|
['feed/atom', 'FeedController@atom'],
|
||||||
['login', 'AuthController@showLogin'],
|
['login', 'AuthController@showLogin'],
|
||||||
['login', 'AuthController@handleLogin', ['POST']],
|
['login', 'AuthController@handleLogin', ['POST']],
|
||||||
['logout', 'AuthController@handleLogout', ['GET', 'POST']],
|
['logout', 'AuthController@handleLogout', ['GET', 'POST']],
|
||||||
['mood', 'MoodController'],
|
['mood', 'MoodController'],
|
||||||
['mood', 'MoodController@handleSetMood', ['POST']],
|
['mood', 'MoodController@handlePost', ['POST']],
|
||||||
['setup', 'AdminController@showSetup'],
|
['setup', 'AdminController@showSetup'],
|
||||||
['setup', 'AdminController@handleSetup', ['POST']],
|
['setup', 'AdminController@handleSetup', ['POST']],
|
||||||
['tick/{y}/{m}/{d}/{h}/{i}/{s}', 'TickController'],
|
['tick/{y}/{m}/{d}/{h}/{i}/{s}', 'TickController'],
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
// welp this model is overkill
|
// welp this model is overkill
|
||||||
class MoodModel{
|
class EmojiModel{
|
||||||
// This isn't memory-efficient,
|
// This isn't memory-efficient,
|
||||||
// but I think it'll be fine on this app's scales.
|
// but I think it'll be fine on this app's scales.
|
||||||
public static function loadAll(): array {
|
public static function loadAll(): array {
|
||||||
global $db;
|
global $db;
|
||||||
|
|
||||||
$stmt = $db->query("SELECT id, emoji, description FROM mood");
|
$stmt = $db->query("SELECT id, emoji, description FROM emoji");
|
||||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ class MoodModel{
|
|||||||
public static function add(string $emoji, ?string $description): void{
|
public static function add(string $emoji, ?string $description): void{
|
||||||
global $db;
|
global $db;
|
||||||
|
|
||||||
$stmt = $db->prepare("INSERT INTO mood (emoji, description) VALUES (?, ?)");
|
$stmt = $db->prepare("INSERT INTO emoji (emoji, description) VALUES (?, ?)");
|
||||||
$stmt->execute([$emoji, $description]);
|
$stmt->execute([$emoji, $description]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ class MoodModel{
|
|||||||
global $db;
|
global $db;
|
||||||
|
|
||||||
$placeholders = rtrim(str_repeat('?,', count($idsToDelete)), ',');
|
$placeholders = rtrim(str_repeat('?,', count($idsToDelete)), ',');
|
||||||
$stmt = $db->prepare("DELETE FROM mood WHERE id IN ($placeholders)");
|
$stmt = $db->prepare("DELETE FROM emoji WHERE id IN ($placeholders)");
|
||||||
$stmt->execute($idsToDelete);
|
$stmt->execute($idsToDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,8 +4,8 @@ class HomeView {
|
|||||||
ob_start();
|
ob_start();
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<section id="ticks" class="home-ticks">
|
<main id="ticks" class="home-main">
|
||||||
<div class="home-ticks-list">
|
<div class="tick-feed">
|
||||||
<?php foreach ($ticks as $tick): ?>
|
<?php foreach ($ticks as $tick): ?>
|
||||||
<article class="tick">
|
<article class="tick">
|
||||||
<div class="tick-time"><?= htmlspecialchars(Util::relative_time($tick['timestamp'])) ?></div>
|
<div class="tick-time"><?= htmlspecialchars(Util::relative_time($tick['timestamp'])) ?></div>
|
||||||
@ -13,7 +13,7 @@ class HomeView {
|
|||||||
</article>
|
</article>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="home-ticks-pagination">
|
<div class="tick-pagination">
|
||||||
<?php if ($page > 1): ?>
|
<?php if ($page > 1): ?>
|
||||||
<a href="?page=<?= $page - 1 ?>">« Newer</a>
|
<a href="?page=<?= $page - 1 ?>">« Newer</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -21,7 +21,7 @@ class HomeView {
|
|||||||
<a href="?page=<?= $page + 1 ?>">Older »</a>
|
<a href="?page=<?= $page + 1 ?>">Older »</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</main>
|
||||||
|
|
||||||
<?php return ob_get_clean();
|
<?php return ob_get_clean();
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,10 @@ class MoodView {
|
|||||||
<form method="post" class="emoji-form">
|
<form method="post" class="emoji-form">
|
||||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||||
<?= $this->render_emoji_groups($emojiGroups, $currentMood) ?>
|
<?= $this->render_emoji_groups($emojiGroups, $currentMood) ?>
|
||||||
<button type="submit">Set the mood</button>
|
<div class="button-group">
|
||||||
|
<button type="submit" name="action" value="set">Set the mood</button>
|
||||||
|
<button type="submit" name="action" value="clear" class="clear-button">Clear mood</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
|
|||||||
<link rel="self"
|
<link rel="self"
|
||||||
type="application/atom+xml"
|
type="application/atom+xml"
|
||||||
title="<?php echo htmlspecialchars($config->siteTitle) ?> Atom Feed"
|
title="<?php echo htmlspecialchars($config->siteTitle) ?> Atom Feed"
|
||||||
href="<?php echo htmlspecialchars($siteUrl . $basePath) ?>feed/atom" />
|
href="<?php echo htmlspecialchars($siteUrl . $basePath) ?>feed/atom">
|
||||||
<link rel="alternate" href="<?= $siteUrl ?>"/>
|
<link rel="alternate" href="<?= $siteUrl ?>">
|
||||||
<updated><?= $updated ?></updated>
|
<updated><?= $updated ?></updated>
|
||||||
<id><?= $siteUrl ?></id>
|
<id><?= $siteUrl ?></id>
|
||||||
<author>
|
<author>
|
||||||
|
@ -9,15 +9,15 @@ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
|||||||
?>
|
?>
|
||||||
<rss version="2.0">
|
<rss version="2.0">
|
||||||
<channel>
|
<channel>
|
||||||
<title>My tkr</title>
|
<title><?php echo htmlspecialchars($config->siteTitle) ?> RSS Feed</title>
|
||||||
<link rel="self"
|
<link rel="self"
|
||||||
type="application/rss+xml"
|
type="application/rss+xml"
|
||||||
title="<?php echo htmlspecialchars($config->siteTitle) ?> RSS Feed"
|
title="<?php echo htmlspecialchars($config->siteTitle) ?> RSS Feed"
|
||||||
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/rss/" />
|
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/rss/">
|
||||||
<link rel="alternate"
|
<link rel="alternate"
|
||||||
type="text/html"
|
type="text/html"
|
||||||
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath) ?>" />
|
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath) ?>">
|
||||||
<description>My tkr</description>
|
<description><?php echo htmlspecialchars($config->siteDescription) ?></description>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate><?php echo date(DATE_RSS); ?></lastBuildDate>
|
<lastBuildDate><?php echo date(DATE_RSS); ?></lastBuildDate>
|
||||||
<?php foreach ($ticks as $tick):
|
<?php foreach ($ticks as $tick):
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
<link rel="alternate"
|
<link rel="alternate"
|
||||||
type="application/rss+xml"
|
type="application/rss+xml"
|
||||||
title="<?php echo htmlspecialchars($config->siteTitle) ?> RSS Feed"
|
title="<?php echo htmlspecialchars($config->siteTitle) ?> RSS Feed"
|
||||||
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/rss/" />
|
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/rss/">
|
||||||
<link rel="alternate"
|
<link rel="alternate"
|
||||||
type="application/atom+xml"
|
type="application/atom+xml"
|
||||||
title="<?php echo htmlspecialchars($config->siteTitle) ?> Atom Feed"
|
title="<?php echo htmlspecialchars($config->siteTitle) ?> Atom Feed"
|
||||||
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/atom/" />
|
href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath)?>feed/atom/">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>
|
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>
|
||||||
|
@ -5,10 +5,15 @@
|
|||||||
<div class="home-container">
|
<div class="home-container">
|
||||||
<section id="sidebar" class="home-sidebar">
|
<section id="sidebar" class="home-sidebar">
|
||||||
<div class="home-header">
|
<div class="home-header">
|
||||||
<h2 class="site-description"><?= $config->siteDescription ?></h2>
|
<h1 class="site-description"><?= $config->siteDescription ?></h1>
|
||||||
</div>
|
</div>
|
||||||
<p><?= $user->about ?></p>
|
<?php if (!empty($user->about)): ?>
|
||||||
|
<p>About: <?= $user->about ?></p>
|
||||||
|
<?php endif ?>
|
||||||
|
<?php if (!empty($user->website)): ?>
|
||||||
<p>Website: <?= Util::escape_and_linkify($user->website) ?></p>
|
<p>Website: <?= Util::escape_and_linkify($user->website) ?></p>
|
||||||
|
<?php endif ?>
|
||||||
|
<?php if (!empty($user->mood) || Session::isLoggedIn()): ?>
|
||||||
<div class="profile-row">
|
<div class="profile-row">
|
||||||
<div class="mood-bar">
|
<div class="mood-bar">
|
||||||
<span>Current mood: <?= $user->mood ?></span>
|
<span>Current mood: <?= $user->mood ?></span>
|
||||||
@ -17,6 +22,7 @@
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<?php if (Session::isLoggedIn()): ?>
|
<?php if (Session::isLoggedIn()): ?>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="profile-row">
|
<div class="profile-row">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user