folderweb/app/helpers.php

188 lines
6.1 KiB
PHP
Raw Normal View History

<?php
function resolveTemplate(string $templateName): string {
$customTemplate = dirname(__DIR__) . "/custom/templates/$templateName.php";
$defaultTemplate = __DIR__ . "/default/templates/$templateName.php";
return file_exists($customTemplate) ? $customTemplate : $defaultTemplate;
}
function getSubdirectories(string $dir): array {
if (!is_dir($dir)) return [];
return array_filter(
scandir($dir) ?: [],
fn($item) => !in_array($item, ['.', '..']) && is_dir("$dir/$item")
);
}
function extractTitle(string $filePath): ?string {
$files = findAllContentFiles($filePath);
if (empty($files)) return null;
// Check the first content file for a title
$file = $files[0];
$ext = pathinfo($file, PATHINFO_EXTENSION);
$content = file_get_contents($file);
if ($ext === 'md' && preg_match('/^#\s+(.+)$/m', $content, $matches)) {
return trim($matches[1]);
}
if (in_array($ext, ['html', 'php']) && preg_match('/<h1[^>]*>(.*?)<\/h1>/i', $content, $matches)) {
return strip_tags($matches[1]);
}
return null;
}
// Build sorted list items for a directory
function buildListItems(string $dir, Context $ctx, ?array $parentMetadata): array {
$subdirs = getSubdirectories($dir);
$items = array_filter(array_map(function($item) use ($dir, $ctx) {
$itemPath = "$dir/$item";
$metadata = loadMetadata($itemPath);
$coverImage = findCoverImage($itemPath);
$pdfFile = findPdfFile($itemPath);
$title = $metadata['title'] ?? extractTitle($itemPath) ?? $item;
$rawDate = null;
$date = null;
if (isset($metadata['date'])) {
$rawDate = $metadata['date'];
$date = Hooks::apply(Hook::PROCESS_CONTENT, $rawDate, 'date_format');
} else {
$rawDate = extractRawDateFromFolder($item);
if ($rawDate) {
$date = Hooks::apply(Hook::PROCESS_CONTENT, $rawDate, 'date_format');
} else {
$rawDate = date("Y-m-d", filemtime($itemPath));
$date = Hooks::apply(Hook::PROCESS_CONTENT, $rawDate, 'date_format');
}
}
$urlSlug = ($metadata && isset($metadata['slug'])) ? $metadata['slug'] : $item;
$langPrefix = $ctx->get('langPrefix', '');
$baseUrl = $langPrefix . '/' . trim($ctx->requestPath, '/') . '/' . urlencode($urlSlug);
$assetUrl = $langPrefix . '/' . trim($ctx->requestPath, '/') . '/' . urlencode($item);
return [
'title' => $title,
'url' => $baseUrl . '/',
'date' => $date,
'rawDate' => $rawDate,
'summary' => $metadata['summary'] ?? null,
'cover' => $coverImage ? "$assetUrl/$coverImage" : null,
'pdf' => $pdfFile ? "$assetUrl/$pdfFile" : null,
'redirect' => $metadata['redirect'] ?? null,
'dirPath' => $itemPath
];
}, $subdirs));
$sortOrder = strtolower($parentMetadata['order'] ?? 'descending');
if ($sortOrder === 'ascending') {
usort($items, fn($a, $b) => strcmp($a['date'] ?? '', $b['date'] ?? ''));
} else {
usort($items, fn($a, $b) => strcmp($b['date'] ?? '', $a['date'] ?? ''));
}
return $items;
}
function extractRawDateFromFolder(string $folderName): ?string {
if (preg_match('/^(\d{4})-(\d{2})-(\d{2})-/', $folderName, $matches)) {
return $matches[1] . '-' . $matches[2] . '-' . $matches[3];
}
return null;
}
function extractDateFromFolder(string $folderName): ?string {
$raw = extractRawDateFromFolder($folderName);
if ($raw) {
return Hooks::apply(Hook::PROCESS_CONTENT, $raw, 'date_format');
}
return null;
}
function findCoverImage(string $dirPath): ?string {
$found = array_find(
COVER_IMAGE_EXTENSIONS,
fn($ext) => file_exists("$dirPath/cover.$ext")
);
return $found ? "cover.$found" : null;
}
function findPdfFile(string $dirPath): ?string {
$pdfs = glob("$dirPath/*.pdf") ?: [];
return $pdfs ? basename($pdfs[0]) : null;
}
function findPageCss(string $dirPath, string $contentDir): ?array {
$cssFile = "$dirPath/styles.css";
if (!file_exists($cssFile) || !is_file($cssFile)) {
return null;
}
$relativePath = str_replace($contentDir, '', $dirPath);
$relativePath = trim($relativePath, '/');
$cssUrl = '/' . ($relativePath ? $relativePath . '/' : '') . 'styles.css';
return [
'url' => $cssUrl,
'hash' => hash_file('md5', $cssFile)
];
}
function findPageJs(string $dirPath, string $contentDir): ?array {
$jsFile = "$dirPath/script.js";
if (!file_exists($jsFile) || !is_file($jsFile)) {
return null;
}
$relativePath = str_replace($contentDir, '', $dirPath);
$relativePath = trim($relativePath, '/');
$jsUrl = '/' . ($relativePath ? $relativePath . '/' : '') . 'script.js';
return [
'url' => $jsUrl,
'hash' => hash_file('md5', $jsFile)
];
}
function extractMetaDescription(string $dirPath, ?array $metadata): ?string {
// 1. Check for search_description in metadata
if ($metadata && isset($metadata['search_description'])) {
return $metadata['search_description'];
}
// 2. Fall back to summary in metadata
if ($metadata && isset($metadata['summary'])) {
return $metadata['summary'];
}
// 3. Fall back to first paragraph in content files
$files = findAllContentFiles($dirPath);
if (empty($files)) return null;
foreach ($files as $file) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
$content = file_get_contents($file);
if ($ext === 'md') {
$lines = explode("\n", $content);
foreach ($lines as $line) {
$line = trim($line);
if (empty($line) || str_starts_with($line, '#')) continue;
if (strlen($line) > 20) {
return strip_tags($line);
}
}
} elseif (in_array($ext, ['html', 'php'])) {
if (preg_match('/<p[^>]*>(.*?)<\/p>/is', $content, $matches)) {
return strip_tags($matches[1]);
}
}
}
return null;
}