diff --git a/app/config.php b/app/config.php
index cb0071b..9551c08 100644
--- a/app/config.php
+++ b/app/config.php
@@ -14,12 +14,7 @@ $userContentDir = $_SERVER['DOCUMENT_ROOT'];
$demoContentDir = __DIR__ . '/default/content';
// Check if user content directory has actual content (more than just . and ..)
-$hasUserContent = false;
-if (is_dir($userContentDir)) {
- $userFiles = scandir($userContentDir) ?: [];
- $userFiles = array_diff($userFiles, ['.', '..']);
- $hasUserContent = count($userFiles) > 0;
-}
+$hasUserContent = is_dir($userContentDir) && count(scandir($userContentDir) ?: []) > 2;
$contentDir = $hasUserContent ? realpath($userContentDir) : realpath($demoContentDir);
@@ -37,15 +32,7 @@ if (!empty($pathParts[0]) && in_array($pathParts[0], $availableLangs) && $pathPa
$requestPath = implode('/', $pathParts);
}
-// Use custom templates with fallback to defaults
-$customBaseTemplate = dirname(__DIR__) . '/custom/templates/base.php';
-$defaultBaseTemplate = __DIR__ . '/default/templates/base.php';
-$baseTemplate = file_exists($customBaseTemplate) ? $customBaseTemplate : $defaultBaseTemplate;
-
-$customPageTemplate = dirname(__DIR__) . '/custom/templates/page.php';
-$defaultPageTemplate = __DIR__ . '/default/templates/page.php';
-$pageTemplate = file_exists($customPageTemplate) ? $customPageTemplate : $defaultPageTemplate;
-
-$customListTemplate = dirname(__DIR__) . '/custom/templates/list.php';
-$defaultListTemplate = __DIR__ . '/default/templates/list.php';
-$listTemplate = file_exists($customListTemplate) ? $customListTemplate : $defaultListTemplate;
+// Resolve templates with custom fallback to defaults
+$baseTemplate = resolveTemplate('base');
+$pageTemplate = resolveTemplate('page');
+$listTemplate = resolveTemplate('list');
diff --git a/app/constants.php b/app/constants.php
new file mode 100644
index 0000000..e54e340
--- /dev/null
+++ b/app/constants.php
@@ -0,0 +1,7 @@
+= 3) {
// Pattern: name.lang.ext
$fileLang = $parts[count($parts) - 2];
- if (in_array($fileLang, ['no', 'en'])) {
+ if (in_array($fileLang, $availableLangs)) {
// Only include if it matches current language
if ($fileLang === $lang) {
$contentFiles[] = [
'path' => $filePath,
'name' => $file,
- 'sort_key' => $parts[0] // Use base name for sorting
+ 'sort_key' => $parts[0]
];
}
continue;
}
}
- // Default files (no language suffix) - include if current lang is default
- // or if no language-specific version exists
+ // Default files (no language suffix) - include if no language-specific version exists
$baseName = $parts[0];
$hasLangVersion = false;
if ($lang !== $defaultLang) {
// Check if language-specific version exists
- foreach ($extensions as $checkExt) {
+ foreach (CONTENT_EXTENSIONS as $checkExt) {
if (file_exists("$dir/$baseName.$lang.$checkExt")) {
$hasLangVersion = true;
break;
@@ -86,10 +83,7 @@ function resolveTranslatedPath(string $requestPath, string $contentDir, string $
// Check all subdirectories for slug matches
$found = false;
if (is_dir($currentPath)) {
- $subdirs = array_filter(
- scandir($currentPath) ?: [],
- fn($item) => !in_array($item, ['.', '..']) && is_dir("$currentPath/$item")
- );
+ $subdirs = getSubdirectories($currentPath);
foreach ($subdirs as $dir) {
$metadata = loadMetadata("$currentPath/$dir", $lang, $defaultLang);
@@ -123,10 +117,7 @@ function parseRequestPath(string $requestPath, string $contentDir, bool $hasTrai
if (is_dir($contentPath)) {
// Check if directory has subdirectories
- $hasSubdirs = !empty(array_filter(
- scandir($contentPath) ?: [],
- fn($item) => !in_array($item, ['.', '..']) && is_dir("$contentPath/$item")
- ));
+ $hasSubdirs = !empty(getSubdirectories($contentPath));
// If directory has subdirectories, it's an article-type folder (list view)
if ($hasSubdirs) {
@@ -176,12 +167,7 @@ function loadTranslations(string $lang): array {
function buildNavigation(string $contentDir, string $currentLang, string $defaultLang): array {
$navItems = [];
-
- // Scan top-level directories in content
- $items = array_filter(
- scandir($contentDir) ?: [],
- fn($item) => !in_array($item, ['.', '..']) && is_dir("$contentDir/$item")
- );
+ $items = getSubdirectories($contentDir);
foreach ($items as $item) {
$itemPath = "$contentDir/$item";
@@ -204,7 +190,7 @@ function buildNavigation(string $contentDir, string $currentLang, string $defaul
// Extract title and build URL
$title = $metadata['title'] ?? extractTitle($itemPath, $currentLang, $defaultLang) ?? ucfirst($item);
- $langPrefix = $currentLang !== $defaultLang ? "/$currentLang" : '';
+ $langPrefix = getLangPrefix($currentLang, $defaultLang);
// Use translated slug if available
$urlSlug = ($currentLang !== $defaultLang && $metadata && isset($metadata['slug']))
diff --git a/app/helpers.php b/app/helpers.php
index 3bd70ed..0638faf 100644
--- a/app/helpers.php
+++ b/app/helpers.php
@@ -1,5 +1,23 @@
!in_array($item, ['.', '..']) && is_dir("$dir/$item")
+ );
+}
+
+function getLangPrefix(string $currentLang, string $defaultLang): string {
+ return $currentLang !== $defaultLang ? "/$currentLang" : '';
+}
+
function extractTitle(string $filePath, string $lang, string $defaultLang): ?string {
$files = findAllContentFiles($filePath, $lang, $defaultLang);
if (empty($files)) return null;
@@ -37,8 +55,7 @@ function extractDateFromFolder(string $folderName): ?string {
}
function findCoverImage(string $dirPath): ?string {
- $extensions = ['jpg', 'jpeg', 'png', 'webp', 'gif'];
- foreach ($extensions as $ext) {
+ foreach (COVER_IMAGE_EXTENSIONS as $ext) {
if (file_exists("$dirPath/cover.$ext")) {
return "cover.$ext";
}
@@ -47,11 +64,6 @@ function findCoverImage(string $dirPath): ?string {
}
function findPdfFile(string $dirPath): ?string {
- $files = scandir($dirPath) ?: [];
- foreach ($files as $file) {
- if (pathinfo($file, PATHINFO_EXTENSION) === 'pdf') {
- return $file;
- }
- }
- return null;
+ $pdfs = glob("$dirPath/*.pdf");
+ return $pdfs ? basename($pdfs[0]) : null;
}
diff --git a/app/rendering.php b/app/rendering.php
index 94c7c8b..dd3391a 100644
--- a/app/rendering.php
+++ b/app/rendering.php
@@ -1,18 +1,35 @@
buildNavigation($contentDir, $currentLang, $defaultLang),
+ 'homeLabel' => loadMetadata($contentDir, $currentLang, $defaultLang)['slug'] ?? 'Home',
+ 'translations' => loadTranslations($currentLang)
+ ];
+}
+
+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 '' . (new Parsedown())->text(file_get_contents($filePath)) . '';
+ } elseif (in_array($ext, ['html', 'php'])) {
+ include $filePath;
+ }
+ return ob_get_clean();
+}
+
function renderTemplate(string $content, int $statusCode = 200): void {
- global $baseTemplate, $contentDir, $currentLang, $defaultLang;
-
- // Build navigation for templates
- $navigation = buildNavigation($contentDir, $currentLang, $defaultLang);
-
- // Load frontpage metadata for home button label
- $frontpageMetadata = loadMetadata($contentDir, $currentLang, $defaultLang);
- $homeLabel = $frontpageMetadata['slug'] ?? 'Home';
-
- // Load translations
- $translations = loadTranslations($currentLang);
-
+ global $baseTemplate;
+
+ extract(prepareTemplateContext());
+
http_response_code($statusCode);
include $baseTemplate;
exit;
@@ -28,33 +45,16 @@ function renderFile(string $filePath): void {
$ext = pathinfo($realPath, PATHINFO_EXTENSION);
- if (in_array($ext, ['php', 'html', 'md'])) {
- ob_start();
- if ($ext === 'md') {
- if (!class_exists('Parsedown')) {
- require_once __DIR__ . '/vendor/Parsedown.php';
- }
- echo '' . (new Parsedown())->text(file_get_contents($realPath)) . '';
- } else {
- include $realPath;
- }
- $content = ob_get_clean();
+ if (in_array($ext, CONTENT_EXTENSIONS)) {
+ $content = renderContentFile($realPath);
- // Build navigation for templates
- $navigation = buildNavigation($contentDir, $currentLang, $defaultLang);
-
- // Load metadata for current page/directory
+ // Prepare template variables
+ extract(prepareTemplateContext());
+
$pageDir = dirname($realPath);
$pageMetadata = loadMetadata($pageDir, $currentLang, $defaultLang);
$pageTitle = $pageMetadata['title'] ?? null;
- // Load frontpage metadata for home button label
- $frontpageMetadata = loadMetadata($contentDir, $currentLang, $defaultLang);
- $homeLabel = $frontpageMetadata['slug'] ?? 'Home';
-
- // Load translations
- $translations = loadTranslations($currentLang);
-
// Wrap content with page template
ob_start();
include $pageTemplate;
@@ -83,38 +83,14 @@ function renderMultipleFiles(array $filePaths, string $pageDir): void {
}
// Render all content files in order
- $content = '';
- foreach ($filePaths as $filePath) {
- $ext = pathinfo($filePath, PATHINFO_EXTENSION);
-
- ob_start();
- if ($ext === 'md') {
- if (!class_exists('Parsedown')) {
- require_once __DIR__ . '/vendor/Parsedown.php';
- }
- echo '' . (new Parsedown())->text(file_get_contents($filePath)) . '';
- } elseif ($ext === 'html') {
- include $filePath;
- } elseif ($ext === 'php') {
- include $filePath;
- }
- $content .= ob_get_clean();
- }
+ $content = implode('', array_map('renderContentFile', $filePaths));
- // Build navigation for templates
- $navigation = buildNavigation($contentDir, $currentLang, $defaultLang);
-
- // Load metadata for current page/directory
+ // Prepare template variables
+ extract(prepareTemplateContext());
+
$pageMetadata = loadMetadata($pageDir, $currentLang, $defaultLang);
$pageTitle = $pageMetadata['title'] ?? null;
- // Load frontpage metadata for home button label
- $frontpageMetadata = loadMetadata($contentDir, $currentLang, $defaultLang);
- $homeLabel = $frontpageMetadata['slug'] ?? 'Home';
-
- // Load translations
- $translations = loadTranslations($currentLang);
-
// Wrap content with page template
ob_start();
include $pageTemplate;
diff --git a/app/router.php b/app/router.php
index 5ec37b0..77e135d 100644
--- a/app/router.php
+++ b/app/router.php
@@ -1,8 +1,9 @@
text(file_get_contents($file));
- } else {
- include $file;
- }
- }
- $pageContent = ob_get_clean();
+ $pageContent = implode('', array_map('renderContentFile', $contentFiles));
}
// Load metadata for this directory
@@ -79,10 +66,10 @@ switch ($parsedPath['type']) {
$templateName = $metadata['page_template'];
// Add .php extension if not present
if (!str_ends_with($templateName, '.php')) {
- $templateName .= '.php';
+ $templateName = str_replace('.php', '', $templateName);
}
- $customTemplate = dirname(__DIR__) . '/custom/templates/' . $templateName;
- $defaultTemplate = __DIR__ . '/default/templates/' . $templateName;
+ $customTemplate = dirname(__DIR__) . "/custom/templates/$templateName.php";
+ $defaultTemplate = __DIR__ . "/default/templates/$templateName.php";
if (file_exists($customTemplate)) {
$listTemplate = $customTemplate;
@@ -92,13 +79,11 @@ switch ($parsedPath['type']) {
// 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")
- );
+ // Build list items
+ $subdirs = getSubdirectories($dir);
+ $langPrefix = getLangPrefix($currentLang, $defaultLang);
- $items = array_filter(array_map(function($item) use ($dir, $requestPath, $currentLang, $defaultLang) {
+ $items = array_filter(array_map(function($item) use ($dir, $requestPath, $currentLang, $defaultLang, $langPrefix) {
$itemPath = "$dir/$item";
// Check if content exists for current language
@@ -119,20 +104,20 @@ switch ($parsedPath['type']) {
$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;
+ $baseUrl = $langPrefix . '/' . trim($requestPath, '/') . '/' . urlencode($urlSlug);
+
return [
'title' => $title,
'date' => $date,
- 'url' => $langPrefix . '/' . trim($requestPath, '/') . '/' . urlencode($urlSlug),
- 'cover' => $coverImage ? $langPrefix . '/' . trim($requestPath, '/') . '/' . urlencode($urlSlug) . '/' . $coverImage : null,
+ 'url' => $baseUrl,
+ 'cover' => $coverImage ? "$baseUrl/$coverImage" : null,
'summary' => $metadata['summary'] ?? null,
- 'pdf' => $pdfFile ? $langPrefix . '/' . trim($requestPath, '/') . '/' . urlencode($urlSlug) . '/' . $pdfFile : null,
+ 'pdf' => $pdfFile ? "$baseUrl/$pdfFile" : null,
'redirect' => $metadata['redirect'] ?? null
];
}, $subdirs));