ContentAPI voor PHP content bestanden + handleiding in admin

- Nieuwe ContentAPI class beschikbaar als $api in PHP content bestanden
  met methodes: getAllPages, getPage, getMenu, getConfig, buildUrl, etc.
- Admin handleiding pagina op /admin/guide met taalwisselaar
- Zijbalk link naar handleiding in admin menu
- Dubbele alert in config pagina verwijderd
- Handleidingen (nl/en) uitgebreid met Content API referentie
This commit is contained in:
2026-07-28 13:59:32 +02:00
parent e85f6e91e1
commit 90253673ba
9 changed files with 452 additions and 25 deletions
+53 -12
View File
@@ -121,6 +121,10 @@ switch ($route) {
handleMediaList($auth, $appConfig);
break;
case 'guide':
handleGuide($auth, $appConfig);
break;
case 'users':
handleUsers($auth, $appConfig);
break;
@@ -662,24 +666,28 @@ function handleConfig(AdminAuth $auth, array $config): void
$configData = file_exists($configJson) ? json_decode(file_get_contents($configJson), true) : [];
if (!is_array($configData)) $configData = [];
// Get available root-level pages
// Get available pages (including subdirectories)
$contentDir = $config['content_dir'];
$availablePages = [];
$availableLangs = $configData['language']['available'] ?? ['nl', 'en'];
if (is_dir($contentDir)) {
$pageMap = [];
foreach (scandir($contentDir) as $file) {
if ($file[0] === '.') continue;
$filePath = $contentDir . '/' . $file;
if (is_file($filePath) && preg_match('/\.(md|php|html)$/', $file)) {
$base = $file;
$langPattern = '/^(' . implode('|', $availableLangs) . ')\.(.+)$/';
if (preg_match($langPattern, $base, $m)) {
$base = $m[2];
}
$pageKey = preg_replace('/\.(md|php|html)$/', '', $base);
$pageMap[$pageKey] = true;
$realContentDir = realpath($contentDir);
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($contentDir, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $fileInfo) {
if (!$fileInfo->isFile()) continue;
$ext = $fileInfo->getExtension();
if (!in_array($ext, ['md', 'php', 'html'])) continue;
$relative = substr($fileInfo->getRealPath(), strlen($realContentDir) + 1);
$base = $relative;
$langPattern = '/^(' . implode('|', $availableLangs) . ')\.(.+)$/';
if (preg_match($langPattern, $base, $m)) {
$base = $m[2];
}
$pageKey = preg_replace('/\.(md|php|html)$/', '', $base);
$pageMap[$pageKey] = true;
}
$availablePages = array_keys($pageMap);
sort($availablePages);
@@ -1360,6 +1368,39 @@ function handleUsers(AdminAuth $auth, array $config): void
require __DIR__ . '/../admin/templates/layout.php';
}
function handleGuide(AdminAuth $auth, array $config): void
{
$user = $auth->getCurrentUser();
$csrf = $auth->getCsrfToken();
// Determine language for guide
$lang = $_GET['lang'] ?? 'nl';
if (!in_array($lang, ['nl', 'en'])) $lang = 'nl';
$guideFile = __DIR__ . '/../guide/' . $lang . '.codepress.md';
if (!file_exists($guideFile)) {
$guideFile = __DIR__ . '/../guide/en.codepress.md';
$lang = 'en';
}
$rawContent = file_get_contents($guideFile);
// Parse markdown using CommonMark if available
$content = '';
if (class_exists('League\CommonMark\CommonMarkConverter')) {
$converter = new League\CommonMark\CommonMarkConverter([
'html_input' => 'allow',
'allow_unsafe_links' => false,
]);
$content = $converter->convert($rawContent)->getContent();
} else {
$content = '<pre>' . htmlspecialchars($rawContent) . '</pre>';
}
$route = 'guide';
require __DIR__ . '/../admin/templates/layout.php';
}
// --- Frontmatter helpers ---
function parseFrontmatterField(string $content, string $key, string $default = ''): string