Refactor models. Handle empty ticks. Prep for CSS upload.
This commit is contained in:
parent
04e813f32c
commit
3690317206
@ -8,9 +8,9 @@ Currently very much a work in progress, but it's baically functional.
|
||||
|
||||
Deploy the `/tkr` directory to a web server that supports php. It will work either as the root of a (sub)domain (e.g. tky.mydomain.com) or if served from a subdirectory (e.g. mydomain.com/tkr).
|
||||
|
||||
If you serve it from a subdirectory, set the value of `$basePath` in `/app/Config.php` to the subdirectory name, excluding the trailing slash (e.g. `/tkr`)
|
||||
If you serve it from a subdirectory, set the value of `$basePath` in `config/init.php` to the subdirectory name, excluding the trailing slash (e.g. `/tkr`)
|
||||
|
||||
It provides an rss feed at `/rss` relative to where it's being served (e.g. `/tkr/rss` if served from `/tkr/`). Each rss entry links to an individual post (which I call "ticks").
|
||||
It provides an rss feed at `/rss` and an atom feed at `/atom` relative to where it's being served (e.g. `/tkr/rss` if served from `/tkr/`). Each rss entry links to an individual post (which I call "ticks").
|
||||
|
||||
## Serving
|
||||
|
||||
|
@ -169,13 +169,6 @@ label {
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.upload-container {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.fieldset-items {
|
||||
margin-bottom: 14px;
|
||||
display: grid;
|
||||
@ -293,6 +286,12 @@ label {
|
||||
- Once the width exceeds that (e.g. desktops), it will convert to horizontal alignment
|
||||
*/
|
||||
@media (min-width: 600px) {
|
||||
label {
|
||||
text-align: right;
|
||||
padding-top: 10px; /* Match input padding */
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.home-container {
|
||||
grid-template-columns: 1fr 2fr;
|
||||
grid-gap: 2em;
|
||||
@ -306,12 +305,6 @@ label {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: right;
|
||||
padding-top: 10px; /* Match input padding */
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
grid-column: 2; /* Align with input column */
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ loadClasses();
|
||||
|
||||
// Everything's loaded. Now we can start ticking.
|
||||
Util::confirm_setup();
|
||||
$config = Config::load();
|
||||
$config = ConfigModel::load();
|
||||
Session::start();
|
||||
Session::generateCsrfToken();
|
||||
|
||||
|
@ -3,8 +3,8 @@ class AdminController extends Controller {
|
||||
// GET handler
|
||||
// render the admin page
|
||||
public function index(){
|
||||
$config = Config::load();
|
||||
$user = User::load();
|
||||
$config = ConfigModel::load();
|
||||
$user = UserModel::load();
|
||||
|
||||
$vars = [
|
||||
'user' => $user,
|
||||
@ -17,22 +17,22 @@ class AdminController extends Controller {
|
||||
// POST handler
|
||||
// save updated settings
|
||||
public function handleSave(){
|
||||
$config = Config::load();
|
||||
$config = ConfigModel::load();
|
||||
|
||||
if (!Config::isFirstSetup()) {
|
||||
if (!ConfigModel::isFirstSetup()) {
|
||||
if (!Session::isLoggedIn()){
|
||||
header('Location: ' . $config->basePath . '/login');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$user = User::load();
|
||||
$user = UserModel::load();
|
||||
|
||||
// handle form submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$errors = [];
|
||||
|
||||
// User profile
|
||||
// UserModel profile
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$displayName = trim($_POST['display_name'] ?? '');
|
||||
$about = trim($_POST['about'] ?? '');
|
||||
@ -115,11 +115,15 @@ class AdminController extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if (Config::isFirstSetup()){
|
||||
Config::completeSetup();
|
||||
if (ConfigModel::isFirstSetup()){
|
||||
ConfigModel::completeSetup();
|
||||
}
|
||||
|
||||
header('Location: ' . $config->basePath . '/admin');
|
||||
exit;
|
||||
}
|
||||
|
||||
private function getCustomCss(){
|
||||
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
class AuthController extends Controller {
|
||||
function showLogin(?string $error = null){
|
||||
$config = Config::load();
|
||||
$config = ConfigModel::load();
|
||||
$csrf_token = Session::getCsrfToken();
|
||||
|
||||
$vars = [
|
||||
@ -14,7 +14,7 @@ class AuthController extends Controller {
|
||||
}
|
||||
|
||||
function handleLogin(){
|
||||
$config = Config::load();
|
||||
$config = ConfigModel::load();
|
||||
|
||||
$error = '';
|
||||
|
||||
@ -48,7 +48,7 @@ class AuthController extends Controller {
|
||||
|
||||
function handleLogout(){
|
||||
Session::end();
|
||||
$config = Config::load();
|
||||
$config = ConfigModel::load();
|
||||
header('Location: ' . $config->basePath);
|
||||
exit;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
class FeedController extends Controller {
|
||||
private Config $config;
|
||||
private ConfigModel $config;
|
||||
private array $ticks;
|
||||
private array $vars;
|
||||
|
||||
public function __construct(){
|
||||
$this->config = Config::load();
|
||||
$this->ticks = iterator_to_array(Tick::streamTicks($this->config->itemsPerPage));
|
||||
$this->config = ConfigModel::load();
|
||||
$this->ticks = iterator_to_array(TickModel::streamTicks($this->config->itemsPerPage));
|
||||
$this->vars = [
|
||||
'config' => $this->config,
|
||||
'ticks' => $this->ticks,
|
||||
|
@ -4,12 +4,12 @@ class HomeController extends Controller {
|
||||
// renders the homepage view.
|
||||
public function index(){
|
||||
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
|
||||
$config = Config::load();
|
||||
$user = User::load();
|
||||
$config = ConfigModel::load();
|
||||
$user = UserModel::load();
|
||||
|
||||
$limit = $config->itemsPerPage;
|
||||
$offset = ($page - 1) * $limit;
|
||||
$ticks = iterator_to_array(Tick::streamTicks($limit, $offset));
|
||||
$ticks = iterator_to_array(TickModel::streamTicks($limit, $offset));
|
||||
|
||||
$view = new HomeView();
|
||||
$tickList = $view->renderTicksSection($config->siteDescription, $ticks, $page, $limit);
|
||||
@ -34,11 +34,13 @@ class HomeController extends Controller {
|
||||
}
|
||||
|
||||
// save the tick
|
||||
Tick::save($_POST['tick']);
|
||||
if (trim($_POST['tick'])){
|
||||
TickModel::save($_POST['tick']);
|
||||
}
|
||||
}
|
||||
|
||||
// get the config
|
||||
$config = Config::load();
|
||||
$config = ConfigModel::load();
|
||||
|
||||
// redirect to the index (will show the latest tick if one was sent)
|
||||
header('Location: ' . $config->basePath);
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
class MoodController extends Controller {
|
||||
public function index(){
|
||||
$config = Config::load();
|
||||
$user = User::load();
|
||||
$config = ConfigModel::load();
|
||||
$user = UserModel::load();
|
||||
$view = new MoodView();
|
||||
|
||||
$moodPicker = $view->render_mood_picker(self::get_emojis_with_labels(), $user->mood);
|
||||
@ -23,8 +23,8 @@
|
||||
}
|
||||
|
||||
// Get the data we need
|
||||
$config = Config::load();
|
||||
$user = User::load();
|
||||
$config = ConfigModel::load();
|
||||
$user = UserModel::load();
|
||||
$mood = $_POST['mood'];
|
||||
|
||||
// set the mood
|
||||
|
@ -3,7 +3,7 @@
|
||||
class TickController extends Controller{
|
||||
// every tick is identified by its timestamp
|
||||
public function index(string $year, string $month, string $day, string $hour, string $minute, string $second){
|
||||
$model = new Tick();
|
||||
$model = new TickModel();
|
||||
$tick = $model->get($year, $month, $day, $hour, $minute, $second);
|
||||
$this->render('tick.php', $tick);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class Session {
|
||||
}
|
||||
|
||||
public static function isLoggedIn(): bool {
|
||||
//echo "User ID set: ". isset($_SESSION['user_id']). "<br/>";
|
||||
//echo "UserModel ID set: ". isset($_SESSION['user_id']). "<br/>";
|
||||
//exit;
|
||||
return isset($_SESSION['user_id']);
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ class Util {
|
||||
// See if there's any data in the tables
|
||||
$user_count = (int) $db->query("SELECT COUNT(*) FROM user")->fetchColumn();
|
||||
$settings_count = (int) $db->query("SELECT COUNT(*) FROM settings")->fetchColumn();
|
||||
$config = Config::load();
|
||||
$config = ConfigModel::load();
|
||||
|
||||
// If either table has no records and we aren't on /admin
|
||||
if ($user_count === 0 || $settings_count === 0){
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
class Config {
|
||||
class ConfigModel {
|
||||
// properties and default values
|
||||
public string $siteTitle = 'My tkr';
|
||||
public string $siteDescription = '';
|
||||
@ -41,7 +41,7 @@ class Config {
|
||||
public function save(): self {
|
||||
$db = Util::get_db();
|
||||
|
||||
if (!Config::isFirstSetup()){
|
||||
if (!ConfigModel::isFirstSetup()){
|
||||
$stmt = $db->prepare("UPDATE settings SET site_title=?, site_description=?, base_url=?, base_path=?, items_per_page=? WHERE id=1");
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO settings (id, site_title, site_description, base_url, base_path, items_per_page) VALUES (1, ?, ?, ?, ?, ?)");
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
class Tick {
|
||||
class TickModel {
|
||||
// Everything in this class just reads from and writes to the filesystem
|
||||
// It doesn't maintain state, so everything's just a static function
|
||||
public static function streamTicks(int $limit, int $offset = 0): Generator {
|
||||
@ -95,7 +95,7 @@ class Tick {
|
||||
return [
|
||||
'tickTime' => $tickTime,
|
||||
'tick' => $tick,
|
||||
'config' => Config::load(),
|
||||
'config' => ConfigModel::load(),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
class User {
|
||||
class UserModel {
|
||||
// properties
|
||||
public string $username = '';
|
||||
public string $displayName = '';
|
||||
@ -30,7 +30,7 @@ class User {
|
||||
public function save(): self {
|
||||
$db = Util::get_db();
|
||||
|
||||
if (!Config::isFirstSetup()){
|
||||
if (!ConfigModel::isFirstSetup()){
|
||||
$stmt = $db->prepare("UPDATE user SET username=?, display_name=?, about=?, website=?, mood=? WHERE id=1");
|
||||
} else {
|
||||
$stmt = $db->prepare("INSERT INTO user (id, username, display_name, about, website, mood) VALUES (1, ?, ?, ?, ?, ?)");
|
@ -1,5 +1,5 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var User $user */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<?php /** @var UserModel $user */ ?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@ -13,14 +13,14 @@
|
||||
<form method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<fieldset>
|
||||
<legend>User settings</legend>
|
||||
<legend>UserModel settings</legend>
|
||||
<div class="fieldset-items">
|
||||
<label>Username <span class=required></span></label>
|
||||
<label>Username <span class=required>*</span></label>
|
||||
<input type="text"
|
||||
name="username"
|
||||
value="<?= $user->username ?>"
|
||||
required>
|
||||
<label>Display name <span class=required></span></label>
|
||||
<label>Display name <span class=required>*</span></label>
|
||||
<input type="text"
|
||||
name="display_name"
|
||||
value="<?= $user->displayName ?>"
|
||||
@ -38,41 +38,70 @@
|
||||
<fieldset>
|
||||
<legend>Site settings</legend>
|
||||
<div class="fieldset-items">
|
||||
<label>Title <span class=required></span></label>
|
||||
<label>Title <span class=required>*</span></label>
|
||||
<input type="text"
|
||||
name="site_title"
|
||||
value="<?= $config->siteTitle ?>"
|
||||
required>
|
||||
<label>Description <span class=required></span></label>
|
||||
<label>Description <span class=required>*</span></label>
|
||||
<input type="text"
|
||||
name="site_description"
|
||||
value="<?= $config->siteDescription ?>">
|
||||
<label>Base URL </label>
|
||||
<label>Base URL <span class=required>*</span></label>
|
||||
<input type="text"
|
||||
name="base_url"
|
||||
value="<?= $config->baseUrl ?>"
|
||||
required>
|
||||
<label>Base path <span class=required></span></label>
|
||||
<label>Base path <span class=required>*</span></label>
|
||||
<input type="text"
|
||||
name="base_path"
|
||||
value="<?= $config->basePath ?>"
|
||||
required>
|
||||
<label>Items per page (max 50) <span class=required></span></label>
|
||||
<label>Items per page (max 50) <span class=required>*</span></label>
|
||||
<input type="number"
|
||||
name="items_per_page"
|
||||
value="<?= $config->itemsPerPage ?>" min="1" max="50"
|
||||
required>
|
||||
</div>
|
||||
<div class="fieldset-items">
|
||||
<label for="setCssFile">Set CSS File</label>
|
||||
<select id="setCssFile" name="css_file">
|
||||
<option value="">Default</option>
|
||||
</select>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Change password</legend>
|
||||
<div class="fieldset-items">
|
||||
<label>New password: </label>
|
||||
<label>New password</label>
|
||||
<input type="password" name="password">
|
||||
<label>Confirm new password: </label>
|
||||
<label>Confirm new password</label>
|
||||
<input type="password" name="confirm_password">
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>CSS Upload</legend>
|
||||
<div class="fieldset-items">
|
||||
<form action="/upload-css" method="post" enctype="multipart/form-data">
|
||||
<label for="uploadCssFile">Select File to Upload</label>
|
||||
<input type="file"
|
||||
id="uploadCssFile"
|
||||
name="uploadCssFile"
|
||||
accept=".css">
|
||||
<div class="file-info">
|
||||
<strong>File Requirements:</strong><br>
|
||||
• Must be a valid CSS file (.css extension)<br>
|
||||
• Maximum size: 2MB<br>
|
||||
• Will be scanned for malicious content
|
||||
</div>
|
||||
<label for="description">Description (optional)</label>
|
||||
<textarea id="description"
|
||||
name="description"
|
||||
placeholder="Describe this CSS file..."></textarea>
|
||||
<button type="submit" class="upload-btn">Upload CSS File</button>
|
||||
</form>
|
||||
</div>
|
||||
</fieldset>
|
||||
<button type="submit" class="submit-btn">Save Settings</button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<?php /** @var array $ticks */ ?>
|
||||
<?php
|
||||
$siteTitle = htmlspecialchars($config->siteTitle);
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<?php /** @var array $ticks */ ?>
|
||||
<?php
|
||||
// Need to have a little php here because the starting xml tag
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php /** @var bool $isLoggedIn */ ?>
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var User $user */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<?php /** @var UserModel $user */ ?>
|
||||
<?php /** @var string $tickList */ ?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<?php /** @var string $csrf_token */ ?>
|
||||
<?php /** @var string $error */ ?>
|
||||
<!DOCTYPE html>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<?php /** @var string $moodPicker */ ?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<title><?= $config->siteTitle ?></title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<div class="navbar">
|
||||
<a href="<?= $config->basePath ?>">home</a>
|
||||
<a href="<?= $config->basePath ?>feed/rss">rss</a>
|
||||
|
@ -53,7 +53,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
<h1>Let’s Set Up Your tkr</h1>
|
||||
<form method="post">
|
||||
<h3>User settings</h3>
|
||||
<h3>UserModel settings</h3>
|
||||
<label>Username: <input type="text" name="username" required></label><br>
|
||||
<label>Display name: <input type="text" name="display_name" required></label><br>
|
||||
<label>Password: <input type="password" name="password" required></label><br>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php /** @var Config $config */ ?>
|
||||
<?php /** @var ConfigModel $config */ ?>
|
||||
<?php /** @var Date $tickTime */ ?>
|
||||
<?php /** @var string $tick */ ?>
|
||||
<!DOCTYPE html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user