Naming fixes. Add partials. Get single ticks working with clean urls.
This commit is contained in:
		
							parent
							
								
									97e2c205a3
								
							
						
					
					
						commit
						78ebb67fc0
					
				@ -1,4 +1,16 @@
 | 
			
		||||
<?php
 | 
			
		||||
// Store and validate request data
 | 
			
		||||
$method = $_SERVER['REQUEST_METHOD'];
 | 
			
		||||
$request = $_SERVER['REQUEST_URI'];
 | 
			
		||||
$path = parse_url($request, PHP_URL_PATH);
 | 
			
		||||
 | 
			
		||||
// return a 404 if a request for a .php file gets this far.
 | 
			
		||||
if (preg_match('/\.php$/', $path)) {
 | 
			
		||||
    http_response_code(404);
 | 
			
		||||
    echo '<h1>404 Not Found</h1>';
 | 
			
		||||
    exit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Define all the important paths
 | 
			
		||||
define('APP_ROOT', dirname(dirname(__FILE__)));
 | 
			
		||||
define('SRC_DIR', APP_ROOT . '/src');
 | 
			
		||||
@ -34,18 +46,6 @@ Session::start();
 | 
			
		||||
Session::generateCsrfToken();
 | 
			
		||||
$config = Config::load();
 | 
			
		||||
 | 
			
		||||
// Get request data
 | 
			
		||||
$method = $_SERVER['REQUEST_METHOD'];
 | 
			
		||||
$request = $_SERVER['REQUEST_URI'];
 | 
			
		||||
$path = parse_url($request, PHP_URL_PATH);
 | 
			
		||||
 | 
			
		||||
// return a 404 if a request for a .php file gets this far.
 | 
			
		||||
if (preg_match('/\.php$/', $path)) {
 | 
			
		||||
    http_response_code(404);
 | 
			
		||||
    echo '<h1>404 Not Found</h1>';
 | 
			
		||||
    exit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove the base path from the URL
 | 
			
		||||
// and strip the trailing slash from the resulting route
 | 
			
		||||
if (strpos($path, $config->basePath) === 0) {
 | 
			
		||||
@ -100,6 +100,7 @@ $routeHandlers = [
 | 
			
		||||
    ['mood', 'MoodController@handleMood', ['POST']],
 | 
			
		||||
    ['feed/rss', 'FeedController@rss'],
 | 
			
		||||
    ['feed/atom', 'FeedController@atom'],
 | 
			
		||||
    ['tick/{y}/{m}/{d}/{h}/{i}/{s}', 'TickController'],
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
// Set content type
 | 
			
		||||
 | 
			
		||||
@ -18,8 +18,8 @@ class AdminController extends Controller {
 | 
			
		||||
    // POST handler
 | 
			
		||||
    // save updated settings
 | 
			
		||||
    public function handleSave(){
 | 
			
		||||
        $isLoggedIn = isset($_SESSION['user_id']);
 | 
			
		||||
        if (!$isLoggedIn){
 | 
			
		||||
        //$isLoggedIn = isset($_SESSION['user_id']);
 | 
			
		||||
        if (!Session::isLoggedIn()){
 | 
			
		||||
            header('Location: ' . $config->basePath . 'login.php');
 | 
			
		||||
            exit;
 | 
			
		||||
        }
 | 
			
		||||
@ -6,7 +6,6 @@ class HomeController extends Controller {
 | 
			
		||||
    // renders the homepage view.
 | 
			
		||||
    public function index(){
 | 
			
		||||
        $page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
 | 
			
		||||
        $isLoggedIn = isset($_SESSION['user_id']);
 | 
			
		||||
        $config = Config::load();
 | 
			
		||||
        $user = User::load();
 | 
			
		||||
 | 
			
		||||
@ -18,10 +17,9 @@ class HomeController extends Controller {
 | 
			
		||||
        $tickList = $view->renderTicksSection($config->siteDescription, $ticks, $page, $limit);
 | 
			
		||||
 | 
			
		||||
        $vars = [
 | 
			
		||||
            'isLoggedIn' => $isLoggedIn,
 | 
			
		||||
            'config'     => $config,
 | 
			
		||||
            'user'       => $user,
 | 
			
		||||
            'tickList'      => $tickList,
 | 
			
		||||
            'tickList'   => $tickList,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $this->render("home.php", $vars);
 | 
			
		||||
							
								
								
									
										11
									
								
								src/Controller/TickController/TickController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/Controller/TickController/TickController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
        $tick = $model->get($year, $month, $day, $hour, $minute, $second);       
 | 
			
		||||
        $this->render('tick.php', $tick);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -24,6 +24,10 @@ class Session {
 | 
			
		||||
        return $_SESSION['csrf_token'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function isLoggedIn(): bool {
 | 
			
		||||
        return isset($_SESSION['user_id']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function end(): void {
 | 
			
		||||
        $_SESSION = [];
 | 
			
		||||
        session_destroy();
 | 
			
		||||
 | 
			
		||||
@ -104,6 +104,17 @@ class Util {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function tick_time_to_tick_path($tickTime){
 | 
			
		||||
        [$date, $time] = explode(' ', $tickTime);
 | 
			
		||||
        $dateParts = explode('-', $date);
 | 
			
		||||
        $timeParts = explode(':', $time);
 | 
			
		||||
 | 
			
		||||
        [$year, $month, $day] = $dateParts;
 | 
			
		||||
        [$hour, $minute, $second] = $timeParts;
 | 
			
		||||
 | 
			
		||||
        return "$year/$month/$day/$hour/$minute/$second";        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: Move to model base class?
 | 
			
		||||
    public static function get_db(): PDO {
 | 
			
		||||
        Util::verify_data_dir(DATA_DIR, true);
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
<?php
 | 
			
		||||
class Tick {
 | 
			
		||||
 | 
			
		||||
    // 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 {
 | 
			
		||||
        $tick_files = glob(TICKS_DIR . '/*/*/*.txt');
 | 
			
		||||
        usort($tick_files, fn($a, $b) => strcmp($b, $a)); // sort filenames in reverse chronological order
 | 
			
		||||
@ -73,5 +74,30 @@ class Tick {
 | 
			
		||||
        // write the tick to the file (the file will be created if it doesn't exist)
 | 
			
		||||
        $content = $time . "|" . $tick . "\n";
 | 
			
		||||
        file_put_contents($filename, $content, FILE_APPEND);
 | 
			
		||||
    }        
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public static function get(string $y, string $m, string $d, string $H, string $i, string $s): array{
 | 
			
		||||
        $tickTime = new DateTime("$y-$m-$d $H:$i:$s");
 | 
			
		||||
        $timestamp = "$H:$i:$s";
 | 
			
		||||
        $file = TICKS_DIR . "/$y/$m/$d.txt";
 | 
			
		||||
            
 | 
			
		||||
        if (!file_exists($file)) {
 | 
			
		||||
            http_response_code(404);
 | 
			
		||||
            echo "Tick not found: $file.";
 | 
			
		||||
            exit;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
 | 
			
		||||
        foreach ($lines as $line) {
 | 
			
		||||
            if (str_starts_with($line, $timestamp)) {
 | 
			
		||||
                $tick = Util::escape_and_linkify(explode('|', $line)[1]);
 | 
			
		||||
 | 
			
		||||
                return [
 | 
			
		||||
                    'tickTime' => $tickTime,
 | 
			
		||||
                    'tick' => $tick,
 | 
			
		||||
                    'config' => Config::load(),
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,14 @@
 | 
			
		||||
<?php /** @var Config $config */ ?>
 | 
			
		||||
<?php /** @var User $user */ ?>
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <title><?= $config->siteTitle ?></title>
 | 
			
		||||
        <meta charset="UTF-8">
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
        <link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css">
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/head.php'?>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
        <h1>Admin</h1>
 | 
			
		||||
        <div><a href="<?= $config->basePath ?>">Back to home</a></div>
 | 
			
		||||
        <div>
 | 
			
		||||
            <form method="post">
 | 
			
		||||
                <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
 | 
			
		||||
 | 
			
		||||
@ -27,9 +27,9 @@ echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
 | 
			
		||||
    [$hour, $minute, $second] = $timeParts;
 | 
			
		||||
 | 
			
		||||
    $tickPath = "$year/$month/$day/$hour/$minute/$second";
 | 
			
		||||
    $tickUrl = htmlspecialchars($basePath . "tick.php?path=" . $tickPath);
 | 
			
		||||
    $tickUrl = htmlspecialchars($basePath . "tick/$tickPath");
 | 
			
		||||
    $tickTime = date(DATE_ATOM, strtotime($tick['timestamp']));
 | 
			
		||||
        $tickText = htmlspecialchars($tick['tick']);
 | 
			
		||||
    $tickText = htmlspecialchars($tick['tick']);
 | 
			
		||||
?>
 | 
			
		||||
  <entry>
 | 
			
		||||
    <title><?= $tickText ?></title>
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,6 @@ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
 | 
			
		||||
    <language>en-us</language>
 | 
			
		||||
    <lastBuildDate><?php echo date(DATE_RSS); ?></lastBuildDate>
 | 
			
		||||
<?php foreach ($ticks as $tick):
 | 
			
		||||
    // TODO: Make this a util function.
 | 
			
		||||
    [$date, $time] = explode(' ', $tick['timestamp']);
 | 
			
		||||
    $dateParts = explode('-', $date);
 | 
			
		||||
    $timeParts = explode(':', $time);
 | 
			
		||||
@ -27,7 +26,7 @@ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
 | 
			
		||||
?>
 | 
			
		||||
    <item>
 | 
			
		||||
        <title><?php echo htmlspecialchars($tick['tick']); ?></title>
 | 
			
		||||
        <link><?php echo htmlspecialchars($config->basePath . "tick.php?path=$tickPath"); ?></link>
 | 
			
		||||
        <link><?php echo htmlspecialchars($config->basePath . "tick/$tickPath"); ?></link>
 | 
			
		||||
        <description><?php echo htmlspecialchars($tick['tick']); ?></description>
 | 
			
		||||
        <pubDate><?php echo date(DATE_RSS, strtotime($tick['timestamp'])); ?></pubDate>
 | 
			
		||||
        <guid><?php echo htmlspecialchars($tickPath); ?></guid>
 | 
			
		||||
 | 
			
		||||
@ -2,26 +2,13 @@
 | 
			
		||||
<?php /** @var Config $config */ ?>
 | 
			
		||||
<?php /** @var User $user */ ?>
 | 
			
		||||
<?php /** @var string $tickList */ ?>
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <title><?= $config->siteTitle ?></title>
 | 
			
		||||
        <meta charset="UTF-8">
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
        <link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css?v=<?= time() ?>">
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/head.php'?>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <div class="home-navbar">
 | 
			
		||||
            <a href="<?= $config->basePath ?>feed/rss">rss</a>
 | 
			
		||||
            <a href="<?= $config->basePath ?>feed/atom">atom</a>
 | 
			
		||||
<?php if (!$isLoggedIn): ?>
 | 
			
		||||
            <a href="<?= $config->basePath ?>login">login</a>
 | 
			
		||||
<?php else: ?>
 | 
			
		||||
            <a href="<?= $config->basePath ?>admin">admin</a>
 | 
			
		||||
            <a href="<?= $config->basePath ?>logout">logout</a>
 | 
			
		||||
<?php endif; ?>
 | 
			
		||||
        </div>
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>
 | 
			
		||||
        <div class="home-container">
 | 
			
		||||
            <section id="sidebar" class="home-sidebar">
 | 
			
		||||
                <div class="home-header">
 | 
			
		||||
@ -32,12 +19,12 @@
 | 
			
		||||
                <div class="profile-row">
 | 
			
		||||
                    <div class="mood-bar">
 | 
			
		||||
                        <span>Current mood: <?= $user->mood ?></span>
 | 
			
		||||
<?php if ($isLoggedIn): ?>
 | 
			
		||||
<?php if (Session::isLoggedIn()): ?>
 | 
			
		||||
                        <a href="<?= $config->basePath ?>mood">Change</a>
 | 
			
		||||
<?php endif; ?>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
<?php if ($isLoggedIn): ?>
 | 
			
		||||
<?php if (Session::isLoggedIn()): ?>
 | 
			
		||||
                <hr/>
 | 
			
		||||
                <div class="profile-row">
 | 
			
		||||
                    <form class="tick-form" method="post">
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,13 @@
 | 
			
		||||
<?php /** @var Config $config */ ?>
 | 
			
		||||
<?php /** @var string $csrfToken */ ?>
 | 
			
		||||
<?php /** @var string $error */ ?>
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <title><?= $config->siteTitle ?></title>
 | 
			
		||||
        <meta charset="UTF-8">
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
        <link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css?v=<?= time() ?>">
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/head.php'?>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>
 | 
			
		||||
    <h2>Login</h2>
 | 
			
		||||
<?php if ($error): ?>
 | 
			
		||||
    <p style="color:red"><?=  htmlspecialchars($error) ?></p>
 | 
			
		||||
 | 
			
		||||
@ -1,19 +1,13 @@
 | 
			
		||||
<?php /** @var Config $config */ ?>
 | 
			
		||||
<?php /** @var string $moodPicker */ ?>
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <title><?= $config->siteTitle ?></title>
 | 
			
		||||
        <meta charset="UTF-8">
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
        <link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css">
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/head.php'?>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>
 | 
			
		||||
        <h2>How are you feeling?</h2>
 | 
			
		||||
 | 
			
		||||
<?php echo $moodPicker; ?>
 | 
			
		||||
 | 
			
		||||
        <a class="back-link" href="<?= htmlspecialchars($config->basePath) ?>">Back to home</a>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										5
									
								
								templates/partials/head.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								templates/partials/head.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
<?php /** @var Config $config */ ?>
 | 
			
		||||
        <title><?= $config->siteTitle ?></title>
 | 
			
		||||
        <meta charset="UTF-8">
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
        <link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css?v=<?= time() ?>">
 | 
			
		||||
							
								
								
									
										12
									
								
								templates/partials/navbar.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								templates/partials/navbar.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
<?php /** @var Config $config */ ?>
 | 
			
		||||
        <div class="navbar">
 | 
			
		||||
            <a href="<?= $config->basePath ?>">home</a>
 | 
			
		||||
            <a href="<?= $config->basePath ?>feed/rss">rss</a>
 | 
			
		||||
            <a href="<?= $config->basePath ?>feed/atom">atom</a>
 | 
			
		||||
<?php if (!Session::isLoggedIn()): ?>
 | 
			
		||||
            <a href="<?= $config->basePath ?>login">login</a>
 | 
			
		||||
<?php else: ?>
 | 
			
		||||
            <a href="<?= $config->basePath ?>admin">admin</a>
 | 
			
		||||
            <a href="<?= $config->basePath ?>logout">logout</a>
 | 
			
		||||
<?php endif; ?>
 | 
			
		||||
        </div>
 | 
			
		||||
@ -1,10 +1,5 @@
 | 
			
		||||
<?php
 | 
			
		||||
#require_once __DIR__ . '/../bootstrap.php';
 | 
			
		||||
 | 
			
		||||
#confirm_setup();
 | 
			
		||||
 | 
			
		||||
// If we got past confirm_setup(), then setup isn't complete.
 | 
			
		||||
$db = get_db();
 | 
			
		||||
$db = Utli::get_db();
 | 
			
		||||
 | 
			
		||||
// Handle submitted form
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
 | 
			
		||||
 | 
			
		||||
@ -1,32 +1,15 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
$path = $_GET['path'] ?? '';
 | 
			
		||||
$parts = explode('/', $path);
 | 
			
		||||
 | 
			
		||||
if (count($parts) !== 6) {
 | 
			
		||||
    http_response_code(400);
 | 
			
		||||
    echo "Invalid tick path.";
 | 
			
		||||
    exit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[$y, $m, $d, $H, $i, $s] = $parts;
 | 
			
		||||
$timestamp = "$H:$i:$s";
 | 
			
		||||
$file = TICKS_DIR . "/$y/$m/$d.txt";
 | 
			
		||||
 | 
			
		||||
if (!file_exists($file)) {
 | 
			
		||||
    http_response_code(404);
 | 
			
		||||
    echo "Tick not found.";
 | 
			
		||||
    exit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
 | 
			
		||||
foreach ($lines as $line) {
 | 
			
		||||
    if (str_starts_with($line, $timestamp)) {
 | 
			
		||||
        echo "<h1>Tick from $timestamp on $y-$m-$d</h1>";
 | 
			
		||||
        echo "<p>" . escape_and_linkify(explode('|', $line)[1]) . "</p>";
 | 
			
		||||
        exit;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
http_response_code(404);
 | 
			
		||||
echo "Tick not found.";
 | 
			
		||||
<?php /** @var Config $config */ ?>
 | 
			
		||||
<?php /** @var Date $tickTime */ ?>
 | 
			
		||||
<?php /** @var string $tick */ ?>
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/head.php'?>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
        <h1>Tick from <?= $tickTime->format('Y-m-d H:i:s'); ?></h1>
 | 
			
		||||
        <p><?= $tick ?></p>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user