diff --git a/custom/plugins/page/news-preview.php b/custom/plugins/page/news-preview.php new file mode 100644 index 0000000..ad0fcfc --- /dev/null +++ b/custom/plugins/page/news-preview.php @@ -0,0 +1,322 @@ + + * + * + * + * Available sizes: + * - 'small': Horizontal scrolling row of compact cards (cover, title, date) + * - 'medium': Responsive wrapping grid (cover, title, date) + * - 'large': Responsive wrapping grid with summary (cover, title, date, summary) + */ + +function newsPreviewT(string $key): string { + $ctx = $GLOBALS['ctx'] ?? null; + $translations = $ctx?->get('translations', []) ?? []; + $fallbacks = [ + 'heading' => 'Siste nytt', + 'read_more' => 'Les mer', + 'see_all' => 'Se alle nyheter', + ]; + return $translations["news_preview.$key"] ?? $fallbacks[$key] ?? $key; +} + +function newsPreviewBuildItems(int $count): array { + $ctx = $GLOBALS['ctx'] ?? null; + if (!$ctx) return []; + + $newsDir = $ctx->contentDir . '/nyheter'; + if (!is_dir($newsDir)) return []; + + $langPrefix = $ctx->get('langPrefix', ''); + $subdirs = getSubdirectories($newsDir); + + $items = []; + foreach ($subdirs as $dir) { + $itemPath = "$newsDir/$dir"; + $metadata = loadMetadata($itemPath); + $title = $metadata['title'] ?? extractTitle($itemPath) ?? $dir; + + $rawDate = $metadata['date'] ?? extractRawDateFromFolder($dir); + $date = $rawDate ? Hooks::apply(Hook::PROCESS_CONTENT, $rawDate, 'date_format') : null; + + $cover = findCoverImage($itemPath); + $slug = $metadata['slug'] ?? $dir; + + $items[] = [ + 'title' => $title, + 'url' => $langPrefix . '/nyheter/' . urlencode($slug) . '/', + 'date' => $date, + 'rawDate' => $rawDate, + 'summary' => $metadata['summary'] ?? extractMetaDescription($itemPath, $metadata), + 'cover' => $cover ? $langPrefix . '/nyheter/' . urlencode($dir) . '/' . $cover : null, + ]; + } + + usort($items, fn($a, $b) => strcmp($b['rawDate'] ?? '', $a['rawDate'] ?? '')); + return array_slice($items, 0, $count); +} + +function newsPreviewRenderSmall(array $items, string $langPrefix): string { + $heading = htmlspecialchars(newsPreviewT('heading')); + $seeAll = htmlspecialchars(newsPreviewT('see_all')); + $seeAllUrl = htmlspecialchars($langPrefix . '/nyheter/'); + + $cards = ''; + foreach ($items as $item) { + $title = htmlspecialchars($item['title']); + $url = htmlspecialchars($item['url']); + $date = $item['date'] ? '

' . htmlspecialchars($item['date']) . '

' : ''; + $cover = $item['cover'] + ? '' . $title . '' + : ''; + + $cards .= << + {$cover} +
+

{$title}

+ {$date} +
+ + HTML; + } + + return << +
+

{$heading}

+ {$seeAll} +
+
+ {$cards} +
+ + HTML; +} + +function newsPreviewRenderMedium(array $items, string $langPrefix): string { + $heading = htmlspecialchars(newsPreviewT('heading')); + $seeAll = htmlspecialchars(newsPreviewT('see_all')); + $seeAllUrl = htmlspecialchars($langPrefix . '/nyheter/'); + + $cards = ''; + foreach ($items as $item) { + $title = htmlspecialchars($item['title']); + $url = htmlspecialchars($item['url']); + $date = $item['date'] ? '

' . htmlspecialchars($item['date']) . '

' : ''; + $cover = $item['cover'] + ? '' . $title . '' + : ''; + + $cards .= << + {$cover} +

{$title}

+ {$date} + + HTML; + } + + return << +
+

{$heading}

+ {$seeAll} +
+
+ {$cards} +
+ + HTML; +} + +function newsPreviewRenderLarge(array $items, string $langPrefix): string { + $heading = htmlspecialchars(newsPreviewT('heading')); + $readMore = htmlspecialchars(newsPreviewT('read_more')); + $seeAll = htmlspecialchars(newsPreviewT('see_all')); + $seeAllUrl = htmlspecialchars($langPrefix . '/nyheter/'); + + $cards = ''; + foreach ($items as $item) { + $title = htmlspecialchars($item['title']); + $url = htmlspecialchars($item['url']); + $date = $item['date'] ? '

' . htmlspecialchars($item['date']) . '

' : ''; + $cover = $item['cover'] + ? '' . $title . '' + : ''; + $summary = $item['summary'] + ? '

' . htmlspecialchars($item['summary']) . '

' + : ''; + + $cards .= << + {$cover} +

{$title}

+ {$date} + {$summary} + {$readMore} + + HTML; + } + + return << +
+

{$heading}

+ {$seeAll} +
+
+ {$cards} +
+ + HTML; +} + +function newsPreviewGetStyles(): string { + static $included = false; + if ($included) return ''; + $included = true; + + return <<<'STYLES' + +STYLES; +} + +/** + * Render a news preview section. + * + * @param int $count Number of news items to show (default: 3) + * @param string $size Display size: 'small', 'medium', or 'large' (default: 'medium') + * @return string The complete HTML for the news preview section + */ +function news_preview(int $count = 3, string $size = 'medium'): string { + $ctx = $GLOBALS['ctx'] ?? null; + if (!$ctx) return ''; + + $items = newsPreviewBuildItems($count); + if (empty($items)) return ''; + + $langPrefix = $ctx->get('langPrefix', ''); + + $html = newsPreviewGetStyles(); + $html .= match ($size) { + 'small' => newsPreviewRenderSmall($items, $langPrefix), + 'large' => newsPreviewRenderLarge($items, $langPrefix), + default => newsPreviewRenderMedium($items, $langPrefix), + }; + + return $html; +}