!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>/i', $content, $matches)) { return strip_tags($matches[1]); } return null; } function formatNorwegianDate(string $dateString): string { if (preg_match('/^(\d{4})-(\d{2})-(\d{2})/', $dateString, $matches)) { $months = ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember']; $day = (int)$matches[3]; $month = $months[(int)$matches[2] - 1]; $year = $matches[1]; return "$day. $month $year"; } return $dateString; } function extractDateFromFolder(string $folderName): ?string { if (preg_match('/^(\d{4})-(\d{2})-(\d{2})-/', $folderName, $matches)) { return formatNorwegianDate($matches[1] . '-' . $matches[2] . '-' . $matches[3]); } 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 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

tag content if (preg_match('/]*>(.*?)<\/p>/is', $content, $matches)) { return strip_tags($matches[1]); } } } return null; }