folderweb/app/router.php
Ruben 149ba03359 Add modular architecture to router
Extract configuration, helpers, content processing, and rendering logic
into separate files

Refactor router to use modular components
2025-11-01 22:50:02 +01:00

152 lines
5.9 KiB
PHP

<?php
// Load modular components
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/helpers.php';
require_once __DIR__ . '/content.php';
require_once __DIR__ . '/rendering.php';
// Check for assets in /custom/assets/ served at root level
$assetPath = dirname(__DIR__) . '/custom/assets/' . $requestPath;
if (file_exists($assetPath) && is_file($assetPath)) {
header('Content-Type: ' . (mime_content_type($assetPath) ?: 'application/octet-stream'));
readfile($assetPath);
exit;
}
// Handle frontpage
if (empty($requestPath)) {
// Find all content files in the root content directory
$contentFiles = findAllContentFiles($contentDir, $currentLang, $defaultLang);
if (!empty($contentFiles)) {
renderMultipleFiles($contentFiles, $contentDir);
}
}
// Parse and handle request
$parsedPath = parseRequestPath($requestPath, $contentDir, $hasTrailingSlash, $currentLang, $defaultLang);
switch ($parsedPath['type']) {
case 'page':
// Page-type folder with content files (no subdirectories)
// Redirect to add trailing slash if needed
if (!empty($parsedPath['needsSlash'])) {
header('Location: ' . rtrim($_SERVER['REQUEST_URI'], '/') . '/', true, 301);
exit;
}
renderMultipleFiles($parsedPath['files'], $parsedPath['path']);
case 'file':
// Direct file access or legacy single file
// Redirect to add trailing slash if this is a directory-based page
if (!empty($parsedPath['needsSlash'])) {
header('Location: ' . rtrim($_SERVER['REQUEST_URI'], '/') . '/', true, 301);
exit;
}
renderFile($parsedPath['path']);
case 'directory':
$dir = $parsedPath['path'];
if (file_exists("$dir/index.php")) {
renderFile("$dir/index.php");
}
// Check for page content files in this directory
$pageContent = null;
$contentFiles = findAllContentFiles($dir, $currentLang, $defaultLang);
if (!empty($contentFiles)) {
ob_start();
foreach ($contentFiles as $file) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
if ($ext === 'md') {
if (!class_exists('Parsedown')) {
require_once __DIR__ . '/vendor/Parsedown.php';
}
echo (new Parsedown())->text(file_get_contents($file));
} else {
include $file;
}
}
$pageContent = ob_get_clean();
}
// Load metadata for this directory
$metadata = loadMetadata($dir, $currentLang, $defaultLang);
// Select list template based on metadata page_template
if (isset($metadata['page_template']) && !empty($metadata['page_template'])) {
$templateName = $metadata['page_template'];
// Add .php extension if not present
if (!str_ends_with($templateName, '.php')) {
$templateName .= '.php';
}
$customTemplate = dirname(__DIR__) . '/custom/templates/' . $templateName;
$defaultTemplate = __DIR__ . '/default/templates/' . $templateName;
if (file_exists($customTemplate)) {
$listTemplate = $customTemplate;
} elseif (file_exists($defaultTemplate)) {
$listTemplate = $defaultTemplate;
}
// If template doesn't exist, fall back to default $listTemplate
}
// Default directory listing
$subdirs = array_filter(
scandir($dir) ?: [],
fn($item) => !in_array($item, ['.', '..']) && is_dir("$dir/$item")
);
$items = array_filter(array_map(function($item) use ($dir, $requestPath, $currentLang, $defaultLang) {
$itemPath = "$dir/$item";
// Check if content exists for current language
if ($currentLang !== $defaultLang) {
$contentFiles = findAllContentFiles($itemPath, $currentLang, $defaultLang);
if (empty($contentFiles)) return null;
}
$metadata = loadMetadata($itemPath, $currentLang, $defaultLang);
$coverImage = findCoverImage($itemPath);
$pdfFile = findPdfFile($itemPath);
$title = $metadata['title'] ?? extractTitle($itemPath, $currentLang, $defaultLang) ?? $item;
$date = null;
if (isset($metadata['date'])) {
$date = formatNorwegianDate($metadata['date']);
} else {
$date = extractDateFromFolder($item) ?: date("F d, Y", filemtime($itemPath));
}
$langPrefix = $currentLang !== $defaultLang ? "/$currentLang" : '';
// Use translated slug if available, otherwise use folder name
$urlSlug = ($currentLang !== $defaultLang && $metadata && isset($metadata['slug']))
? $metadata['slug']
: $item;
return [
'title' => $title,
'date' => $date,
'url' => $langPrefix . '/' . trim($requestPath, '/') . '/' . urlencode($urlSlug),
'cover' => $coverImage ? $langPrefix . '/' . trim($requestPath, '/') . '/' . urlencode($urlSlug) . '/' . $coverImage : null,
'summary' => $metadata['summary'] ?? null,
'pdf' => $pdfFile ? $langPrefix . '/' . trim($requestPath, '/') . '/' . urlencode($urlSlug) . '/' . $pdfFile : null,
'redirect' => $metadata['redirect'] ?? null
];
}, $subdirs));
ob_start();
include $listTemplate;
$content = ob_get_clean();
// Build navigation for base template
$navigation = buildNavigation($contentDir, $currentLang, $defaultLang);
include $baseTemplate;
exit;
case 'not_found':
renderTemplate("<h1>404 Not Found</h1><p>The requested resource was not found.</p>", 404);
}