Add global and page-level plugin support Implement language-aware content filtering Add month translations to language files Refactor date formatting to use translations Move translation loading to plugin system Improve content availability checks
114 lines
3.8 KiB
PHP
114 lines
3.8 KiB
PHP
<?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 $lang, string $defaultLang): ?string {
|
|
$files = findAllContentFiles($filePath, $lang, $defaultLang, []);
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
function extractDateFromFolder(string $folderName, string $lang): ?string {
|
|
if (preg_match('/^(\d{4})-(\d{2})-(\d{2})-/', $folderName, $matches)) {
|
|
return formatDate($matches[1] . '-' . $matches[2] . '-' . $matches[3], $lang);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function findCoverImage(string $dirPath): ?string {
|
|
// PHP 8.4: array_find() - cleaner than foreach
|
|
$found = array_find(
|
|
COVER_IMAGE_EXTENSIONS,
|
|
fn($ext) => file_exists("$dirPath/cover.$ext")
|
|
);
|
|
return $found ? "cover.$found" : null;
|
|
}
|
|
|
|
function findPdfFile(string $dirPath): ?string {
|
|
// PHP 8.4: array_find() with glob
|
|
$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;
|
|
}
|
|
|
|
// Generate URL path relative to content directory
|
|
$relativePath = str_replace($contentDir, '', $dirPath);
|
|
$relativePath = trim($relativePath, '/');
|
|
$cssUrl = '/' . ($relativePath ? $relativePath . '/' : '') . 'styles.css';
|
|
|
|
return [
|
|
'url' => $cssUrl,
|
|
'hash' => hash_file('md5', $cssFile)
|
|
];
|
|
}
|
|
|
|
function extractMetaDescription(string $dirPath, ?array $metadata, string $lang, string $defaultLang): ?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, $lang, $defaultLang, []);
|
|
if (empty($files)) return null;
|
|
|
|
foreach ($files as $file) {
|
|
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
|
$content = file_get_contents($file);
|
|
|
|
if ($ext === 'md') {
|
|
// Skip headings and extract first paragraph
|
|
$lines = explode("\n", $content);
|
|
foreach ($lines as $line) {
|
|
$line = trim($line);
|
|
if (empty($line) || str_starts_with($line, '#')) continue;
|
|
if (strlen($line) > 20) { // Ignore very short lines
|
|
return strip_tags($line);
|
|
}
|
|
}
|
|
} elseif (in_array($ext, ['html', 'php'])) {
|
|
// Extract first <p> tag content
|
|
if (preg_match('/<p[^>]*>(.*?)<\/p>/is', $content, $matches)) {
|
|
return strip_tags($matches[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|