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
 | ||||
|         $db->exec("CREATE TABLE IF NOT EXISTS mood (
 | ||||
|         $db->exec("CREATE TABLE IF NOT EXISTS emoji(
 | ||||
|             id INTEGER PRIMARY KEY, | ||||
|             emoji TEXT UNIQUE NOT NULL, | ||||
|             description TEXT NOT NULL | ||||
| @ -185,7 +185,7 @@ function validate_tables(): void { | ||||
|     $appTables[] = "settings"; | ||||
|     $appTables[] = "user"; | ||||
|     $appTables[] = "css"; | ||||
|     $appTables[] = "mood"; | ||||
|     $appTables[] = "emoji"; | ||||
| 
 | ||||
|     $db = get_db(); | ||||
| 
 | ||||
|  | ||||
| @ -77,6 +77,10 @@ fieldset.emoji-group { | ||||
|     gap: 0.3em; | ||||
| } | ||||
| 
 | ||||
| h1.site-description { | ||||
|     font-size: 1.3em; | ||||
| } | ||||
| 
 | ||||
| .delete-emoji-fieldset .fieldset-items { | ||||
|     display: block; | ||||
|     grid-template-columns: none; | ||||
| @ -293,7 +297,7 @@ label.description { | ||||
|     font-size: 1.0em; | ||||
| } | ||||
| 
 | ||||
| .pagination a {  | ||||
| .tick-pagination a {  | ||||
|     margin: 0 5px;  | ||||
|     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); | ||||
|         } | ||||
| 
 | ||||
|         // Shows the custom emoji management page
 | ||||
|         public function showCustomEmoji(){ | ||||
|             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'])) { | ||||
|         public function handlePost(){ | ||||
|             if ($_SERVER['REQUEST_METHOD'] === 'POST') { | ||||
|                 // ensure that the session is valid before proceeding
 | ||||
|                 if (!Session::validateCsrfToken($_POST['csrf_token'])) { | ||||
|                     die('Invalid CSRF token'); | ||||
| @ -97,9 +25,17 @@ | ||||
|                 // Get the data we need
 | ||||
|                 global $config; | ||||
|                 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 = $user->save(); | ||||
|              | ||||
| @ -110,7 +46,7 @@ | ||||
|         } | ||||
| 
 | ||||
|         private static function getEmojisWithLabels(): array { | ||||
|             $customEmoji = MoodModel::loadAll(); | ||||
|             $customEmoji = EmojiModel::loadAll(); | ||||
| 
 | ||||
|             if (!empty($customEmoji)){ | ||||
|                 $custom = []; | ||||
|  | ||||
| @ -10,15 +10,15 @@ class Router { | ||||
|         ['admin', 'AdminController@handleSave', ['POST']], | ||||
|         ['admin/css', 'CssController'], | ||||
|         ['admin/css', 'CssController@handlePost', ['POST']], | ||||
|         ['admin/emoji', 'MoodController@showCustomEmoji'], | ||||
|         ['admin/emoji', 'MoodController@handlePost', ['POST']], | ||||
|         ['admin/emoji', 'EmojiController'], | ||||
|         ['admin/emoji', 'EmojiController@handlePost', ['POST']], | ||||
|         ['feed/rss', 'FeedController@rss'], | ||||
|         ['feed/atom', 'FeedController@atom'], | ||||
|         ['login', 'AuthController@showLogin'], | ||||
|         ['login', 'AuthController@handleLogin', ['POST']], | ||||
|         ['logout', 'AuthController@handleLogout', ['GET', 'POST']], | ||||
|         ['mood', 'MoodController'], | ||||
|         ['mood', 'MoodController@handleSetMood', ['POST']], | ||||
|         ['mood', 'MoodController@handlePost', ['POST']], | ||||
|         ['setup', 'AdminController@showSetup'], | ||||
|         ['setup', 'AdminController@handleSetup', ['POST']], | ||||
|         ['tick/{y}/{m}/{d}/{h}/{i}/{s}', 'TickController'], | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <?php | ||||
| // welp this model is overkill
 | ||||
| class MoodModel{ | ||||
| class EmojiModel{ | ||||
|     // This isn't memory-efficient,
 | ||||
|     // but I think it'll be fine on this app's scales.
 | ||||
|     public static function loadAll(): array { | ||||
|         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); | ||||
|     } | ||||
| 
 | ||||
| @ -15,7 +15,7 @@ class MoodModel{ | ||||
|     public static function add(string $emoji, ?string $description): void{ | ||||
|         global $db; | ||||
| 
 | ||||
|         $stmt = $db->prepare("INSERT INTO mood (emoji, description) VALUES (?, ?)"); | ||||
|         $stmt = $db->prepare("INSERT INTO emoji (emoji, description) VALUES (?, ?)"); | ||||
|         $stmt->execute([$emoji, $description]); | ||||
|     } | ||||
| 
 | ||||
| @ -23,7 +23,7 @@ class MoodModel{ | ||||
|         global $db; | ||||
| 
 | ||||
|         $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); | ||||
|     } | ||||
| } | ||||
| @ -4,8 +4,8 @@ class HomeView { | ||||
|         ob_start(); | ||||
|         ?>
 | ||||
| 
 | ||||
|         <section id="ticks" class="home-ticks"> | ||||
|             <div class="home-ticks-list"> | ||||
|         <main id="ticks" class="home-main"> | ||||
|             <div class="tick-feed"> | ||||
|             <?php foreach ($ticks as $tick): ?>
 | ||||
|                 <article class="tick"> | ||||
|                     <div class="tick-time"><?= htmlspecialchars(Util::relative_time($tick['timestamp'])) ?></div>
 | ||||
| @ -13,7 +13,7 @@ class HomeView { | ||||
|                 </article> | ||||
|             <?php endforeach; ?>
 | ||||
|             </div> | ||||
|             <div class="home-ticks-pagination"> | ||||
|             <div class="tick-pagination"> | ||||
|             <?php if ($page > 1): ?>
 | ||||
|                 <a href="?page=<?= $page - 1 ?>">« Newer</a> | ||||
|             <?php endif; ?>
 | ||||
| @ -21,7 +21,7 @@ class HomeView { | ||||
|                 <a href="?page=<?= $page + 1 ?>">Older »</a> | ||||
|             <?php endif; ?>
 | ||||
|             </div> | ||||
|         </section> | ||||
|         </main> | ||||
| 
 | ||||
|         <?php return ob_get_clean(); | ||||
|     } | ||||
|  | ||||
| @ -33,7 +33,10 @@ class MoodView { | ||||
|         <form method="post" class="emoji-form"> | ||||
|             <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> | ||||
|             <?= $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> | ||||
|         <?php | ||||
| 
 | ||||
|  | ||||
| @ -14,8 +14,8 @@ echo '<?xml version="1.0" encoding="utf-8"?>' . "\n"; | ||||
|   <link rel="self" | ||||
|         type="application/atom+xml" | ||||
|         title="<?php echo htmlspecialchars($config->siteTitle) ?> Atom Feed" | ||||
|         href="<?php echo htmlspecialchars($siteUrl . $basePath) ?>feed/atom" /> | ||||
|   <link rel="alternate" href="<?= $siteUrl ?>"/> | ||||
|         href="<?php echo htmlspecialchars($siteUrl . $basePath) ?>feed/atom"> | ||||
|   <link rel="alternate" href="<?= $siteUrl ?>"> | ||||
|   <updated><?= $updated ?></updated>
 | ||||
|   <id><?= $siteUrl ?></id>
 | ||||
|   <author> | ||||
|  | ||||
| @ -9,15 +9,15 @@ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n"; | ||||
| ?>
 | ||||
| <rss version="2.0"> | ||||
| <channel> | ||||
|     <title>My tkr</title> | ||||
|     <title><?php echo htmlspecialchars($config->siteTitle) ?> RSS Feed</title>
 | ||||
|     <link rel="self" | ||||
|           type="application/rss+xml" | ||||
|           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" | ||||
|           type="text/html" | ||||
|           href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath) ?>" /> | ||||
|     <description>My tkr</description> | ||||
|           href="<?php echo htmlspecialchars($config->baseUrl . $config->basePath) ?>"> | ||||
|     <description><?php echo htmlspecialchars($config->siteDescription) ?></description>
 | ||||
|     <language>en-us</language> | ||||
|     <lastBuildDate><?php echo date(DATE_RSS); ?></lastBuildDate>
 | ||||
| <?php foreach ($ticks as $tick): | ||||
|  | ||||
| @ -17,11 +17,11 @@ | ||||
|         <link rel="alternate" | ||||
|               type="application/rss+xml" | ||||
|               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" | ||||
|               type="application/atom+xml" | ||||
|               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> | ||||
|     <body> | ||||
| <?php include TEMPLATES_DIR . '/partials/navbar.php'?>
 | ||||
|  | ||||
| @ -5,10 +5,15 @@ | ||||
|         <div class="home-container"> | ||||
|             <section id="sidebar" class="home-sidebar"> | ||||
|                 <div class="home-header"> | ||||
|                     <h2 class="site-description"><?= $config->siteDescription ?></h2>
 | ||||
|                     <h1 class="site-description"><?= $config->siteDescription ?></h1>
 | ||||
|                 </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>
 | ||||
| <?php endif ?>
 | ||||
| <?php if (!empty($user->mood) || Session::isLoggedIn()): ?>
 | ||||
|                 <div class="profile-row"> | ||||
|                     <div class="mood-bar"> | ||||
|                         <span>Current mood: <?= $user->mood ?></span>
 | ||||
| @ -17,6 +22,7 @@ | ||||
| <?php endif; ?>
 | ||||
|                     </div> | ||||
|                 </div> | ||||
| <?php endif; ?>
 | ||||
| <?php if (Session::isLoggedIn()): ?>
 | ||||
|                 <hr/> | ||||
|                 <div class="profile-row"> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user