folderweb/app/content.php
Ruben a205f2cbd7 Remove language-specific content handling
Refactor to use plugin system for language support

Remove hardcoded language features from core

Move language handling to plugin system

Improve content file discovery

Simplify context creation

Add plugin system documentation

Implement hook system for extensibility

Add template variable hook

Add context storage for plugins

Improve error handling

Refactor rendering logic

Improve list view sorting

Add support for custom list templates

Improve metadata handling

Add plugin system reference documentation
2025-11-25 20:19:12 +01:00

111 lines
3.5 KiB
PHP

<?php
// Find all content files in a directory
function findAllContentFiles(string $dir): array {
if (!is_dir($dir)) return [];
$files = scandir($dir) ?: [];
$contentFiles = [];
foreach ($files as $file) {
if ($file === '.' || $file === '..' || $file === 'index.php') continue;
$ext = pathinfo($file, PATHINFO_EXTENSION);
if (!in_array($ext, CONTENT_EXTENSIONS)) continue;
$filePath = "$dir/$file";
if (!is_file($filePath)) continue;
$contentFiles[] = [
'path' => $filePath,
'name' => $file,
'ext' => $ext
];
}
// Let plugins filter content files (e.g., by language)
$contentFiles = Hooks::apply(Hook::PROCESS_CONTENT, $contentFiles, $dir);
// Sort by filename
usort($contentFiles, fn($a, $b) => strnatcmp($a['name'], $b['name']));
return array_column($contentFiles, 'path');
}
function parseRequestPath(Context $ctx): array {
$requestPath = $ctx->requestPath;
if (empty($requestPath)) {
return ['type' => 'frontpage', 'path' => $ctx->contentDir];
}
$contentPath = $ctx->contentDir . '/' . $requestPath;
// Check if it's a directory
if (is_dir($contentPath)) {
$items = scandir($contentPath) ?: [];
$subdirs = array_filter($items, fn($item) =>
$item !== '.' && $item !== '..' && is_dir("$contentPath/$item")
);
if (!empty($subdirs)) {
return ['type' => 'list', 'path' => $contentPath];
} else {
return ['type' => 'page', 'path' => $contentPath];
}
}
return ['type' => 'not_found', 'path' => $contentPath];
}
function loadMetadata(string $dirPath): ?array {
$metadataFile = "$dirPath/metadata.ini";
if (!file_exists($metadataFile)) return null;
$metadata = parse_ini_file($metadataFile, true);
if (!$metadata) return null;
// Get base metadata (non-array values)
$baseMetadata = array_filter($metadata, fn($key) => !is_array($metadata[$key]), ARRAY_FILTER_USE_KEY);
// Store full metadata for plugins to access
$baseMetadata['_raw'] = $metadata;
// Let plugins modify metadata (e.g., merge language sections)
return Hooks::apply(Hook::PROCESS_CONTENT, $baseMetadata, $dirPath, 'metadata');
}
function buildNavigation(Context $ctx): array {
$items = scandir($ctx->contentDir) ?: [];
$navItems = [];
foreach ($items as $item) {
if ($item === '.' || $item === '..' || !is_dir($ctx->contentDir . "/$item")) continue;
$itemPath = "{$ctx->contentDir}/$item";
$metadata = loadMetadata($itemPath);
// Only include if explicitly marked as menu item
// parse_ini_file returns boolean true as 1, false as empty string, and "true"/"false" as strings
if (!$metadata || !isset($metadata['menu']) || !$metadata['menu']) {
continue;
}
// Extract title
$title = $metadata['title'] ?? extractTitle($itemPath) ?? ucfirst($item);
// Use slug if available, otherwise use folder name
$urlSlug = ($metadata && isset($metadata['slug'])) ? $metadata['slug'] : $item;
$navItems[] = [
'title' => $title,
'url' => '/' . urlencode($urlSlug) . '/',
'order' => (int)($metadata['menu_order'] ?? 999)
];
}
// Sort by menu_order
usort($navItems, fn($a, $b) => $a['order'] <=> $b['order']);
return $navItems;
}