2025-11-01 22:50:02 +01:00
|
|
|
<?php
|
|
|
|
|
|
2025-11-01 22:54:42 +01:00
|
|
|
function prepareTemplateContext(): array {
|
|
|
|
|
global $contentDir, $currentLang, $defaultLang;
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
'navigation' => buildNavigation($contentDir, $currentLang, $defaultLang),
|
|
|
|
|
'homeLabel' => loadMetadata($contentDir, $currentLang, $defaultLang)['slug'] ?? 'Home',
|
|
|
|
|
'translations' => loadTranslations($currentLang)
|
|
|
|
|
];
|
|
|
|
|
}
|
2025-11-01 22:50:02 +01:00
|
|
|
|
2025-11-01 22:54:42 +01:00
|
|
|
function renderContentFile(string $filePath): string {
|
|
|
|
|
$ext = pathinfo($filePath, PATHINFO_EXTENSION);
|
|
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
|
if ($ext === 'md') {
|
|
|
|
|
if (!class_exists('Parsedown')) {
|
|
|
|
|
require_once __DIR__ . '/vendor/Parsedown.php';
|
|
|
|
|
}
|
|
|
|
|
echo '<article>' . (new Parsedown())->text(file_get_contents($filePath)) . '</article>';
|
|
|
|
|
} elseif (in_array($ext, ['html', 'php'])) {
|
|
|
|
|
include $filePath;
|
|
|
|
|
}
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}
|
2025-11-01 22:50:02 +01:00
|
|
|
|
2025-11-01 22:54:42 +01:00
|
|
|
function renderTemplate(string $content, int $statusCode = 200): void {
|
|
|
|
|
global $baseTemplate;
|
|
|
|
|
|
|
|
|
|
extract(prepareTemplateContext());
|
|
|
|
|
|
2025-11-01 22:50:02 +01:00
|
|
|
http_response_code($statusCode);
|
|
|
|
|
include $baseTemplate;
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderFile(string $filePath): void {
|
|
|
|
|
global $baseTemplate, $pageTemplate, $contentDir, $currentLang, $defaultLang;
|
|
|
|
|
|
|
|
|
|
$realPath = realpath($filePath);
|
|
|
|
|
if (!$realPath || !str_starts_with($realPath, $contentDir) || !is_readable($realPath)) {
|
|
|
|
|
renderTemplate("<article><h1>403 Forbidden</h1><p>Access denied.</p></article>", 403);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ext = pathinfo($realPath, PATHINFO_EXTENSION);
|
|
|
|
|
|
2025-11-01 22:54:42 +01:00
|
|
|
if (in_array($ext, CONTENT_EXTENSIONS)) {
|
|
|
|
|
$content = renderContentFile($realPath);
|
2025-11-01 22:50:02 +01:00
|
|
|
|
2025-11-01 22:54:42 +01:00
|
|
|
// Prepare template variables
|
|
|
|
|
extract(prepareTemplateContext());
|
|
|
|
|
|
2025-11-01 22:50:02 +01:00
|
|
|
$pageDir = dirname($realPath);
|
|
|
|
|
$pageMetadata = loadMetadata($pageDir, $currentLang, $defaultLang);
|
|
|
|
|
$pageTitle = $pageMetadata['title'] ?? null;
|
|
|
|
|
|
|
|
|
|
// Wrap content with page template
|
|
|
|
|
ob_start();
|
|
|
|
|
include $pageTemplate;
|
|
|
|
|
$content = ob_get_clean();
|
|
|
|
|
|
|
|
|
|
// Wrap with base template
|
|
|
|
|
include $baseTemplate;
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Serve other file types directly
|
|
|
|
|
header('Content-Type: ' . (mime_content_type($realPath) ?: 'application/octet-stream'));
|
|
|
|
|
readfile($realPath);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderMultipleFiles(array $filePaths, string $pageDir): void {
|
|
|
|
|
global $baseTemplate, $pageTemplate, $contentDir, $currentLang, $defaultLang;
|
|
|
|
|
|
|
|
|
|
// Validate all files are safe
|
|
|
|
|
foreach ($filePaths as $filePath) {
|
|
|
|
|
$realPath = realpath($filePath);
|
|
|
|
|
if (!$realPath || !str_starts_with($realPath, $contentDir) || !is_readable($realPath)) {
|
|
|
|
|
renderTemplate("<article><h1>403 Forbidden</h1><p>Access denied.</p></article>", 403);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Render all content files in order
|
2025-11-01 22:54:42 +01:00
|
|
|
$content = implode('', array_map('renderContentFile', $filePaths));
|
2025-11-01 22:50:02 +01:00
|
|
|
|
2025-11-01 22:54:42 +01:00
|
|
|
// Prepare template variables
|
|
|
|
|
extract(prepareTemplateContext());
|
|
|
|
|
|
2025-11-01 22:50:02 +01:00
|
|
|
$pageMetadata = loadMetadata($pageDir, $currentLang, $defaultLang);
|
|
|
|
|
$pageTitle = $pageMetadata['title'] ?? null;
|
|
|
|
|
|
|
|
|
|
// Wrap content with page template
|
|
|
|
|
ob_start();
|
|
|
|
|
include $pageTemplate;
|
|
|
|
|
$content = ob_get_clean();
|
|
|
|
|
|
|
|
|
|
// Wrap with base template
|
|
|
|
|
include $baseTemplate;
|
|
|
|
|
exit;
|
|
|
|
|
}
|