From 32449d2edd348059ad520a241e951b19f96fc90f Mon Sep 17 00:00:00 2001 From: Ruben Date: Sat, 1 Nov 2025 22:54:42 +0100 Subject: [PATCH] Refactor template and content handling logic Add constants for file extensions Extract helper functions for common operations Improve PDF file detection Simplify directory scanning operations Standardize template resolution Optimize content rendering pipeline --- app/config.php | 23 +++-------- app/constants.php | 7 ++++ app/content.php | 38 ++++++------------ app/helpers.php | 30 +++++++++----- app/rendering.php | 100 ++++++++++++++++++---------------------------- app/router.php | 45 +++++++-------------- 6 files changed, 98 insertions(+), 145 deletions(-) create mode 100644 app/constants.php 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));