Make the homepage an actual template.
This commit is contained in:
		
							parent
							
								
									d3271e43a0
								
							
						
					
					
						commit
						51595c13eb
					
				| @ -22,6 +22,15 @@ server { | ||||
|         alias /var/www/html/public; | ||||
|         index index.php; | ||||
| 
 | ||||
|         # Cache static files | ||||
|         # Note that I don't actually serve most of this (just js and css to start) | ||||
|         # but including them all will let caching work later if I add images or something | ||||
|         location ~* ^/tkr/.+\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|             try_files $uri =404; | ||||
|         } | ||||
| 
 | ||||
|         # index.php is the entry point | ||||
|         # It needs to be sent to php-fpm | ||||
|         # But if someone tries to directly access index.php, that file will throw a 404 | ||||
| @ -60,15 +69,6 @@ server { | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|     # Cache static files | ||||
|     # Note that I don't actually serve most of this (just js and css to start) | ||||
|     # but including them all will let caching work later if I add images or something | ||||
|     location ~* ^/tkr/.+\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|         expires 1y; | ||||
|         add_header Cache-Control "public, immutable"; | ||||
|         try_files $uri =404; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to sensitive directories | ||||
|     location ~ ^/tkr/(storage|lib|vendor|config) { | ||||
|         deny all; | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| define('APP_ROOT', dirname(__FILE__)); | ||||
| define('CLASSES_DIR', APP_ROOT . '/classes'); | ||||
| define('LIB_DIR', APP_ROOT . '/lib'); | ||||
| define('TICKS_DIR', APP_ROOT . '/storage/ticks'); | ||||
| define('DATA_DIR', APP_ROOT . '/storage/db'); | ||||
| define('DB_FILE', DATA_DIR . '/tkr.sqlite'); | ||||
| #define('APP_ROOT', dirname(__FILE__));
 | ||||
| #define('CLASSES_DIR', APP_ROOT . '/classes');
 | ||||
| #define('LIB_DIR', APP_ROOT . '/lib');
 | ||||
| #define('TICKS_DIR', APP_ROOT . '/storage/ticks');
 | ||||
| #define('DATA_DIR', APP_ROOT . '/storage/db');
 | ||||
| #define('DB_FILE', DATA_DIR . '/tkr.sqlite');
 | ||||
| 
 | ||||
| function verify_data_dir(string $dir, bool $allow_create = false): void { | ||||
|     if (!is_dir($dir)) { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| // Made this a class so it could be more obvious where config settings are coming from.
 | ||||
| // Felt too much like magic constants in other files before.
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| // Made this a class so it could be more obvious where config settings are coming from.
 | ||||
| // Felt too much like magic constants in other files before.
 | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require_once CLASSES_DIR . '/User.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require_once CLASSES_DIR . '/User.php';
 | ||||
| 
 | ||||
| require LIB_DIR . '/emoji.php'; | ||||
| #require LIB_DIR . '/emoji.php';
 | ||||
| 
 | ||||
| function save_mood(string $mood): void { | ||||
|     $config = Config::load(); | ||||
|  | ||||
| @ -3,8 +3,6 @@ if (session_status() === PHP_SESSION_NONE) { | ||||
|     session_start(); | ||||
| } | ||||
| 
 | ||||
| $isLoggedIn = isset($_SESSION['username']); | ||||
| 
 | ||||
| function generateCsrfToken() { | ||||
|     if (empty($_SESSION['csrf_token'])) { | ||||
|         $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| function save_tick(string $tick): void { | ||||
|     // build the tick path and filename from the current time
 | ||||
|  | ||||
| @ -38,3 +38,101 @@ function relative_time(string $tickTime): string { | ||||
|     } | ||||
|     return $diff->s . ' second' . ($diff->s != 1 ? 's' : '') . ' ago'; | ||||
| } | ||||
| function verify_data_dir(string $dir, bool $allow_create = false): void { | ||||
|     if (!is_dir($dir)) { | ||||
|         if ($allow_create) { | ||||
|             if (!mkdir($dir, 0770, true)) { | ||||
|                 http_response_code(500); | ||||
|                 echo "Failed to create required directory: $dir"; | ||||
|                 exit; | ||||
|             } | ||||
|         } else { | ||||
|             http_response_code(500); | ||||
|             echo "Required directory does not exist: $dir"; | ||||
|             exit; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (!is_writable($dir)) { | ||||
|         http_response_code(500); | ||||
|         echo "Directory is not writable: $dir"; | ||||
|         exit; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Verify that setup is complete (i.e. the databse is populated).
 | ||||
| // Redirect to setup.php if it isn't.
 | ||||
| function confirm_setup(): void { | ||||
|     $db = get_db(); | ||||
| 
 | ||||
|     // Ensure required tables exist
 | ||||
|     $db->exec("CREATE TABLE IF NOT EXISTS user (
 | ||||
|         id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||
|         username TEXT NOT NULL, | ||||
|         display_name TEXT NOT NULL, | ||||
|         password_hash TEXT NOT NULL, | ||||
|         about TEXT NULL, | ||||
|         website TEXT NULL, | ||||
|         mood TEXT NULL | ||||
|     )");
 | ||||
| 
 | ||||
|     $db->exec("CREATE TABLE IF NOT EXISTS settings (
 | ||||
|         id INTEGER PRIMARY KEY, | ||||
|         site_title TEXT NOT NULL, | ||||
|         site_description TEXT NULL, | ||||
|         base_path TEXT NOT NULL, | ||||
|         items_per_page INTEGER NOT NULL | ||||
|     )");
 | ||||
| 
 | ||||
|     // 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(); | ||||
| 
 | ||||
|     // If either table has no records and we aren't on setup.php, redirect to setup.php
 | ||||
|     if ($user_count === 0 || $settings_count === 0){ | ||||
|         if (basename($_SERVER['PHP_SELF']) !== 'setup.php'){ | ||||
|             header('Location: setup.php'); | ||||
|             exit; | ||||
|         } | ||||
|     } else { | ||||
|         // If setup is complete and we are on setup.php, redirect to index.php.
 | ||||
|         if (basename($_SERVER['PHP_SELF']) === 'setup.php'){ | ||||
|             header('Location: index.php'); | ||||
|             exit; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| function get_db(): PDO { | ||||
|     verify_data_dir(DATA_DIR, true); | ||||
| 
 | ||||
|     try { | ||||
|         $db = new PDO("sqlite:" . DB_FILE); | ||||
|         $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||||
|         $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); | ||||
|     } catch (PDOException $e) { | ||||
|         die("Database connection failed: " . $e->getMessage()); | ||||
|     } | ||||
|      | ||||
|     return $db; | ||||
| } | ||||
| 
 | ||||
| function render_template(string $templateFile, array $vars = []): string { | ||||
|     #$templatePath = TEMPLATES_DIR . '/' . ltrim($templateFile, '/');
 | ||||
|      | ||||
|     if (!file_exists($templateFile)) { | ||||
|         throw new RuntimeException("Template not found: $templatePath"); | ||||
|     } | ||||
| 
 | ||||
|     // Extract variables into local scope
 | ||||
|     extract($vars, EXTR_SKIP); | ||||
| 
 | ||||
|     // Start output buffering
 | ||||
|     ob_start(); | ||||
| 
 | ||||
|     // Include the template (with extracted variables in scope)
 | ||||
|     include $templateFile; | ||||
| 
 | ||||
|     // Return rendered output
 | ||||
|     return ob_get_clean(); | ||||
| } | ||||
| @ -1,7 +1,36 @@ | ||||
| <?php | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| define('APP_ROOT', dirname(dirname(__FILE__))); | ||||
| 
 | ||||
| define('CLASSES_DIR', APP_ROOT . '/classes'); | ||||
| define('LIB_DIR', APP_ROOT . '/lib'); | ||||
| define('STORAGE_DIR', APP_ROOT . '/storage'); | ||||
| define('TEMPLATES_DIR', APP_ROOT . '/templates'); | ||||
| 
 | ||||
| define('TICKS_DIR', STORAGE_DIR . '/ticks'); | ||||
| define('DATA_DIR', STORAGE_DIR . '/db'); | ||||
| define('DB_FILE', DATA_DIR . '/tkr.sqlite'); | ||||
| 
 | ||||
| $include_dirs = [ | ||||
|     LIB_DIR, | ||||
|     CLASSES_DIR, | ||||
| ]; | ||||
| 
 | ||||
| foreach ($include_dirs as $include_dir){ | ||||
|     foreach (glob($include_dir . '/*.php') as $file) { | ||||
|         require_once $file; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| confirm_setup(); | ||||
| 
 | ||||
| $isLoggedIn = isset($_SESSION['user_id']); | ||||
| $config = Config::load(); | ||||
| $user = User::load(); | ||||
| 
 | ||||
| // Define your base path (subdirectory)
 | ||||
| $basePath = '/tkr'; | ||||
| #$basePath = '/tkr';
 | ||||
| 
 | ||||
| // Get HTTP data
 | ||||
| $method = $_SERVER['REQUEST_METHOD']; | ||||
| @ -11,8 +40,15 @@ $request = $_SERVER['REQUEST_URI']; | ||||
| // and strip the trailing slash from the resulting route
 | ||||
| $path = parse_url($request, PHP_URL_PATH); | ||||
| 
 | ||||
| if (strpos($path, $basePath) === 0) { | ||||
|     $path = substr($path, strlen($basePath)); | ||||
| // return a 404 if s request for a .php file gets this far.
 | ||||
| if (preg_match('/\.php$/', $path)) { | ||||
|     http_response_code(404); | ||||
|     echo '<h1>404 Not Found</h1>'; | ||||
|     exit; | ||||
| } | ||||
| 
 | ||||
| if (strpos($path, $config->basePath) === 0) { | ||||
|     $path = substr($path, strlen($config->basePath)); | ||||
| } | ||||
| 
 | ||||
| $path = trim($path, '/'); | ||||
| @ -42,7 +78,21 @@ header('Content-Type: text/html; charset=utf-8'); | ||||
| echo "Path: " . $path; | ||||
| 
 | ||||
| // Define your routes
 | ||||
| route('', function() { | ||||
|     echo '<h1>Home Page</h1>'; | ||||
|     echo '<p>Welcome to the home page!</p>'; | ||||
| route('', function() use ($isLoggedIn, $config, $user) { | ||||
|     #include TEMPLATES_DIR . "/home.php";
 | ||||
|     #echo render_home_page($isLoggedIn, $config, $user);
 | ||||
|     $page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1; | ||||
|     $limit = $config->itemsPerPage; | ||||
|     $offset = ($page - 1) * $limit; | ||||
|     $ticks = iterator_to_array(stream_ticks($limit, $offset)); | ||||
| 
 | ||||
|     $vars = [ | ||||
|         'isLoggedIn' => $isLoggedIn, | ||||
|         'config'     => $config, | ||||
|         'user'       => $user, | ||||
|         'ticks'      => $ticks, | ||||
|     ]; | ||||
| 
 | ||||
|     echo render_template(TEMPLATES_DIR . "/home.php", $vars); | ||||
| }); | ||||
| //isset($_SESSION['user_id'])
 | ||||
| @ -1,14 +0,0 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| 
 | ||||
| confirm_setup(); | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require LIB_DIR . '/session.php'; | ||||
| 
 | ||||
| $config = Config::load(); | ||||
| $_SESSION = []; | ||||
| session_destroy(); | ||||
| 
 | ||||
| header('Location: ' . $config->basePath); | ||||
| exit; | ||||
| @ -1,12 +1,12 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require LIB_DIR . '/session.php'; | ||||
| require LIB_DIR . '/ticks.php'; | ||||
| require LIB_DIR . '/util.php'; | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require LIB_DIR . '/session.php';
 | ||||
| #require LIB_DIR . '/ticks.php';
 | ||||
| #require LIB_DIR . '/util.php';
 | ||||
| 
 | ||||
| 
 | ||||
| // ticks must be sent via POST
 | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require LIB_DIR . '/session.php'; | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require LIB_DIR . '/session.php';
 | ||||
| 
 | ||||
| if (!$isLoggedIn){ | ||||
|     header('Location: ' . $config->basePath . 'login.php'); | ||||
| @ -1,10 +1,10 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require_once LIB_DIR . '/ticks.php'; | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require_once LIB_DIR . '/ticks.php';
 | ||||
| 
 | ||||
| $config = Config::load(); | ||||
| $ticks = iterator_to_array(stream_ticks($config->itemsPerPage)); | ||||
| @ -1,31 +1,15 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| <?php /** @var bool $isLoggedIn */ ?>
 | ||||
| <?php /** @var Config $config */ ?>
 | ||||
| <?php /** @var User $user */ ?>
 | ||||
| <?php /** @var array $ticks */ ?>
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require_once CLASSES_DIR . '/User.php'; | ||||
| require LIB_DIR . '/session.php'; | ||||
| require LIB_DIR . '/ticks.php'; | ||||
| require LIB_DIR . '/util.php'; | ||||
| 
 | ||||
| $config = Config::load(); | ||||
| // I can get away with this before login because there's only one user.
 | ||||
| $user = User::load(); | ||||
| 
 | ||||
| $page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1; | ||||
| $limit = $config->itemsPerPage; | ||||
| $offset = ($page - 1) * $limit; | ||||
| 
 | ||||
| $ticks = iterator_to_array(stream_ticks($limit, $offset)); | ||||
| ?>
 | ||||
| <!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() ?>"> | ||||
|         <link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>/css/tkr.css?v=<?= time() ?>"> | ||||
|     </head> | ||||
|     <body> | ||||
|         <div class="home-navbar"> | ||||
| @ -1,10 +1,10 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require LIB_DIR . '/session.php'; | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require LIB_DIR . '/session.php';
 | ||||
| 
 | ||||
| $config = Config::load(); | ||||
| 
 | ||||
							
								
								
									
										14
									
								
								src/templates/logout.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/templates/logout.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| <?php | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require LIB_DIR . '/session.php';
 | ||||
| 
 | ||||
| $config = Config::load(); | ||||
| $_SESSION = []; | ||||
| session_destroy(); | ||||
| 
 | ||||
| header('Location: ' . $config->basePath); | ||||
| exit; | ||||
| @ -1,10 +1,10 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require_once LIB_DIR . '/ticks.php'; | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require_once LIB_DIR . '/ticks.php';
 | ||||
| 
 | ||||
| $config = Config::load(); | ||||
| $ticks = iterator_to_array(stream_ticks($config->itemsPerPage)); | ||||
| @ -1,11 +1,11 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| require_once CLASSES_DIR . '/Config.php'; | ||||
| require LIB_DIR . '/session.php'; | ||||
| require LIB_DIR . '/mood.php'; | ||||
| #require_once CLASSES_DIR . '/Config.php';
 | ||||
| #require LIB_DIR . '/session.php';
 | ||||
| #require LIB_DIR . '/mood.php';
 | ||||
| 
 | ||||
| 
 | ||||
| // get the config
 | ||||
| @ -1,7 +1,7 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| // If we got past confirm_setup(), then setup isn't complete.
 | ||||
| $db = get_db(); | ||||
| @ -1,9 +1,9 @@ | ||||
| <?php | ||||
| require_once __DIR__ . '/../bootstrap.php'; | ||||
| #require_once __DIR__ . '/../bootstrap.php';
 | ||||
| 
 | ||||
| confirm_setup(); | ||||
| #confirm_setup();
 | ||||
| 
 | ||||
| require LIB_DIR . '/util.php'; | ||||
| #require LIB_DIR . '/util.php';
 | ||||
| 
 | ||||
| $path = $_GET['path'] ?? ''; | ||||
| $parts = explode('/', $path); | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user