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
111 lines
3.5 KiB
PHP
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;
|
|
}
|