Update all guides (NL + EN) for CodePress 2.5.2 features

- Admin guide: RBAC roles, role-based dashboard, plugin types (content/system)
- CodePress developer guide: plugin types, admin plugin API, SCSS compilation, asset serving
- Theme developer guide: SCSS sole CSS source, css_compiled read-only, guide layout
- Content manager guide: layout selection from theme.json, plugin order in frontmatter
- Both NL and EN updated with identical structure
- 35 files updated
This commit is contained in:
2026-08-12 12:05:53 +02:00
parent a9e3b023de
commit 9a5ab351ba
35 changed files with 1493 additions and 255 deletions
+80 -7
View File
@@ -1,11 +1,84 @@
# CMS Architectuur
CodePress is een file-based CMS zonder database. Content, configuratie en gebruikers worden opgeslagen in bestanden.
## Mappenstructuur
```
codepress/
├── cms/core/ # Core engine
├── admin/ # Admin console
├── themes/ # Thema's
├── plugins/ # Plugins
├── content/ # Content
└── public/ # Web root
```
├── cms/ # Core CMS engine
│ ├── core/
│ │ ├── class/
│ │ │ ├── CodePressCMS.php # Hoofd CMS class (routing, rendering, breadcrumb)
│ │ │ ├── ThemeManager.php # Thema-resolver + Twig render + SCSS compile
│ │ │ ├── ContentAPI.php # Read-only API voor PHP content
│ │ │ ├── ContentSecurityPolicy.php # CSP header management
│ │ │ ├── Analytics.php # Bezoekersstatistieken
│ │ │ ├── BotGuard.php # Bot/AI detectie
│ │ │ ├── Cache.php # Cache systeem
│ │ │ ├── GeoIP.php # GeoIP lookup (land, vlag)
│ │ │ ├── Logger.php # Basis logging
│ │ │ ├── LogManager.php # Dynamisch logging (SQLite/syslog)
│ │ │ ├── RateLimiter.php # Rate limiting per IP
│ │ │ ├── RequestLogger.php # Request logging + visitor info
│ │ │ ├── SearchEngine.php # Volledige tekst zoekfunctie
│ │ │ └── AccessibilityManager.php # Accessibility features
│ │ ├── plugin/
│ │ │ ├── PluginManager.php # Plugin loader (hooks, filters, sidebar, admin routes)
│ │ │ └── CMSAPI.php # API voor plugins (getPage, getConfig, etc.)
│ │ ├── config.php # Config loader (leest config.json)
│ │ └── index.php # Bootstrap (autoloader, requires)
│ ├── lang/ # Taalbestanden (nl.php, en.php)
│ └── router.php # PHP dev server router
├── themes/ # Dynamische thema's
│ └── default/ # Standaard thema (views + assets)
│ ├── theme.json # { title, config.default_template, template: layout→.twig }
│ ├── base.twig # Hoofd layout
│ ├── *.twig # Layout templates
│ ├── partials/ # header.twig, navigation.twig, footer.twig
│ └── assets/
│ ├── scss/theme.scss # SCSS bron (enige CSS bron)
│ ├── css_compiled/ # Gegenereerd door scssphp (read-only)
│ ├── css/ # Externe CSS (bootstrap.min.css, etc.)
│ ├── js/ # JavaScript
│ └── img/ # Afbeeldingen
├── admin/ # Admin paneel
│ ├── config/
│ │ ├── app.php # Admin app configuratie
│ │ └── admin.json # Gebruikers & security (file-based, .gitignore'd)
│ ├── src/
│ │ └── AdminAuth.php # Authenticatie + RBAC
│ ├── theme/default/ # Admin thema (views + assets)
│ │ ├── theme.json
│ │ ├── assets/ # CSS, JS, CodeMirror, fonts
│ │ └── views/ # login.twig, layouts/, pages/
│ └── storage/ # Logs, cache, geoip
├── plugins/ # CMS plugins
│ ├── Navigation/ # Essentiële navigatie plugin (beschermd)
│ │ ├── Navigation.php # Plugin code (NIET plugin.php)
│ │ ├── plugin.json # Metadata met type veld
│ │ └── assets/ # SCSS + CSS
│ └── HTMLBlock/ # Voorbeeld sidebar plugin
├── content/ # Website content (.md, .php, .html) — .gitignore'd
├── guide/ # Handleidingen (nl/en)
├── public/ # Web root
│ ├── index.php # Website entry point
│ ├── admin.php # Admin entry point + routing
│ ├── asset.php # Asset server voor Apache (themes/, admin/assets/, plugins/)
│ ├── .htaccess # Stuurt asset URLs door naar asset.php
│ ├── favicon.ico
│ └── robots.txt
├── var/ # Cache (twig) — .gitignore'd
├── config.json # Site configuratie — .gitignore'd
├── composer.json # PHP dependencies (CommonMark, Twig, scssphp)
└── version.php # Versie informatie (2.5.2)
```
## Principes
- **Geen database** — Alles in bestanden (content in `content/`, gebruikers in `admin/config/admin.json`, config in `config.json`)
- **File-based auth** — `AdminAuth` gebruikt bcrypt hashes in `admin.json`, sessies voor login
- **Twig templating** — Themes gebruiken Twig; `ThemeManager` rendert via Twig
- **SCSS compilatie** — `assets/scss/theme.scss``assets/css_compiled/theme.css` via scssphp (read-only output)
- **Plugin systeem** — `PluginManager` laadt content en systeem plugins met hooks/filters
- **Asset serving** — PHP dev router (`cms/router.php`) of Apache (`.htaccess``public/asset.php`)
+81 -4
View File
@@ -10,6 +10,13 @@ $cms->init();
$cms->renderPage($pagePath);
```
Verantwoordelijkheden:
- Routing en pagina rendering
- Breadcrumb generatie (dynamisch: Home > [submappen] > [pagina])
- Guide pagina's laden (`getGuidePage()`)
- Titel extractie uit H1 (`getTitleFromFile()`)
- Weergavenaam verwerking (`formatDisplayName()`)
## ThemeManager.php
Themabeheer in `cms/core/class/ThemeManager.php`:
@@ -19,14 +26,84 @@ $themeManager = new ThemeManager($config);
$themeManager->getActiveTheme();
$themeManager->renderTwig($template, $data);
$themeManager->compileCss($force);
$themeManager->getCssUrl();
```
Verantwoordelijkheden:
- Actief thema resolveren vanuit `config.json`
- `theme.json` laden (title, config.default_template, template mapping)
- Twig environment bouwen (geroot in thema map)
- **SCSS compilatie** — compileert `assets/scss/theme.scss` naar `assets/css_compiled/theme.css` via scssphp
- Layout resolveren naar `.twig` template (fallback op `config.default_template`)
`getCssUrl()` prioriteit: 1) `assets/css/theme.css` (handmatig), 2) `assets/css_compiled/theme.css` (gecompileerd).
## PluginManager.php
Plugin systeem in `cms/core/class/PluginManager.php`:
Plugin systeem in `cms/core/plugin/PluginManager.php`:
```php
$pluginManager = new PluginManager();
$pluginManager->loadPlugins($enabledPlugins);
$pluginManager = new PluginManager($pluginsPath, $enabledPlugins);
$pluginManager->getSidebarContent($allowedPlugins);
$pluginManager->getPluginCssUrls();
$pluginManager->executeHook($name, $params);
```
$pluginManager->getAdminMenuItems();
$pluginManager->handleAdminRoute($route);
$pluginManager->getPluginType($pluginName);
```
Verantwoordelijkheden:
- Plugins laden vanuit `plugins/` mappen (alleen ingeschakelde plugins)
- Plugin bestand: `<PluginName>.php` (NIET `plugin.php`)
- Hooks en filters systeem (`doAction`, `applyFilters`)
- Sidebar content verzamelen van content plugins (`getSidebarContent`)
- Plugin CSS URLs verzamelen (`getPluginCssUrls`)
- **Admin menu items** van systeem plugins (`getAdminMenuItems`)
- **Admin routes** afhandelen via systeem plugins (`handleAdminRoute`)
- **Plugin type** bepalen (`getPluginType``content` of `system`)
- `isPluginViewable` — systeem plugins verschijnen niet in sidebar
## AdminAuth.php
Authenticatie en RBAC in `admin/src/AdminAuth.php`:
```php
$auth = new AdminAuth($appConfig);
$auth->login($username, $password);
$auth->logout();
$auth->hasPermission($route);
$auth->verifyCsrf($token);
```
Constanten:
- `ROLE_PERMISSIONS` — Mapping van rol → toegestane route prefixes. `admin` heeft wildcard `*`.
- `ROLE_LABELS` — Human-readable labels per rol.
Rollen:
| Rol | Label | Permissies |
|-----|-------|-----------|
| `admin` | Admin | Alles (`*`) |
| `content-manager` | Content Beheerder | Content beheer, handleiding |
| `bi-manager` | BI Beheerder | Statistieken, logs, handleiding |
| `site-admin` | Site Admin | Thema, plugins, statistieken, logs, update, handleiding |
Verantwoordelijkheden:
- Session-based authenticatie
- bcrypt password hashing
- CSRF tokens (`verifyCsrf`)
- Brute-force lockout (login attempts tracking)
- RBAC via `hasPermission($route)` — checkt route tegen `ROLE_PERMISSIONS`
## CMSAPI.php
Plugin API in `cms/core/plugin/CMSAPI.php`:
```php
$api = PluginManager::getAPI();
$config = $api->getConfig();
$page = $api->getPage($path);
$content = $api->getContent();
```
Biedt read-only toegang aan plugins tot CMS data (config, pagina's, content).
@@ -1,43 +1,144 @@
# Plugin Development
## Plugin types
CodePress kent twee soorten plugins, bepaald door het `type` veld in `plugin.json`:
- **Content plugins** (`type: "content"`) — Verschijnen in de sidebar en in de plugin selectie op content-edit pagina's. Bieden sidebar content via `getSidebarContent()`.
- **Systeem plugins** (`type: "system"`) — Worden geladen door PluginManager maar verschijnen NIET in de sidebar. Bieden functionaliteit via admin menu, routes en de CMSAPI.
Bij afwezigheid van een `type` veld wordt `content` aangenomen.
## Plugin structuur
```
plugins/MijnPlugin/
├── plugin.json # Plugin metadata
├── plugin.php # Plugin code
── config.json # Optionele configuratie
├── MijnPlugin.php # Plugin code (NIET plugin.php)
├── plugin.json # Metadata met type veld
── config.json # Optionele configuratie
└── assets/
├── scss/mijnplugin.scss # SCSS bron (optioneel)
└── css/mijnplugin.css # CSS (handmatig onderhouden)
```
Plugin bestanden heten `<PluginName>.php` (bijv. `Navigation.php`, `HTMLBlock.php`). `PluginManager` laadt `$pluginDir . '/' . $pluginName . '.php'`.
## plugin.json
```json
{
"name": "Mijn Plugin",
"version": "1.0.0",
"author": "Jouw Naam",
"description": "Beschrijving"
"name": "Mijn Plugin",
"version": "1.0.0",
"author": "Jouw Naam",
"description": "Beschrijving",
"type": "content"
}
```
## plugin.php voorbeeld
- `name` — Weergavenaam
- `type``"content"` of `"system"` (default: `content`)
## Content plugin voorbeeld
```php
<?php
/**
* Plugin: MijnPlugin
* Plugin: MijnPlugin (content)
*/
class MijnPlugin
{
public function getConfig(): array
{
return [
'title' => 'Mijn Plugin',
'type' => 'content',
];
}
echo '<div class="mijn-plugin">Hello World</div>';
public function getSidebarContent(): string
{
return '<p>Hello World</p>';
}
}
```
## Systeem plugin voorbeeld
```php
<?php
/**
* Plugin: MijnSysteem (system)
*/
class MijnSysteem
{
public function getConfig(): array
{
return [
'title' => 'Mijn Systeem',
'type' => 'system',
];
}
public function getAdminMenu(): array
{
return [
['label' => 'Mijn Systeem', 'route' => 'mijn-systeem', 'icon' => 'bi-gear'],
];
}
public function getAdminRoutes(): array
{
return ['mijn-systeem'];
}
public function handleAdminRoute(string $route): void
{
echo '<h1>Mijn Systeem pagina</h1>';
}
}
```
Systeem plugins worden via `PluginManager::getAdminMenuItems()` in de admin sidebar getoond en via `PluginManager::handleAdminRoute()` afgehandeld.
## CMSAPI gebruiken
```php
<?php
require_once '../../cms/core/class/PluginManager.php';
$api = PluginManager::getAPI();
$config = $api->getConfig();
$content = $api->getContent();
```
$page = $api->getPage($path);
```
`setAPI()` wordt automatisch aangeroepen door `PluginManager` als de plugin de methode heeft.
## Plugin CSS
- Plugin CSS in `assets/css/` is handmatig te onderhouden (SCSS compilatie voor plugins is nog niet automatisch)
- Plugin CSS wordt automatisch geladen ná theme CSS (in `base.twig`), zodat thema's plugin styling kunnen overschrijven
- Plugin assets worden geserveerd via `cms/router.php` op URL `/plugins/<Name>/assets/...`
- Implementeer `getCssUrl()` in de plugin klasse om de CSS URL terug te geven
```php
public function getCssUrl(): string
{
return '/plugins/MijnPlugin/assets/css/mijnplugin.css';
}
```
## Hooks en filters
PluginManager auto-registert deze methoden als hooks/filters:
- **Hooks**: `onPageLoad`, `onBeforeRender`, `onAfterRender`, `onSearch`, `onMenuBuild`
- **Filters**: `onContentFilter`, `onTitleFilter`, `onMenuFilter`
```php
public function onPageLoad($page) { /* ... */ }
public function onContentFilter($content) { return $content; }
```
## Essentiële plugins
Essentiële plugins zijn gedefinieerd in `getProtectedPlugins()` in `public/admin.php`. Huidige essentiële plugin: **Navigation**.
Deze plugins kunnen niet worden gedeactiveerd, bewerkt of verwijderd. Voeg altijd de `isProtectedPlugin()` check toe aan nieuwe plugin handlers.
+49 -7
View File
@@ -2,18 +2,60 @@
## Frontend routing
Via `cms/router.php` voor PHP dev server:
Frontend routing verloopt via `cms/router.php` (PHP dev server) of `.htaccess` (Apache). Beide zorgen voor clean URLs.
```php
// Schone URLs: /nl/pagina
// Query: ?page=pagina&lang=nl
### PHP dev server
Start de server met:
```bash
php -S localhost:8080 cms/router.php
```
`cms/router.php` serveert:
- Schone URLs: `/nl/pagina``public/index.php?page=pagina&lang=nl`
- `themes/` assets
- `admin/assets/` assets
- `plugins/` assets
### Apache (live server)
`public/.htaccess` herschrijft URLs naar `public/index.php`. Asset URLs (`/themes/`, `/admin/assets/`, `/plugins/`) worden doorgestuurd naar `public/asset.php`.
`public/asset.php` serveert bestanden vanuit de juiste mappen met het juiste MIME-type:
- `/themes/<name>/assets/...``themes/<name>/assets/...`
- `/admin/assets/...``admin/theme/default/assets/...`
- `/plugins/<name>/assets/...``plugins/<name>/assets/...`
## Admin routing
Via `public/admin.php`:
Admin routing verloopt via `public/admin.php` met clean URLs:
```
/admin/dashboard → ?route=dashboard
/admin/content → ?route=content
/admin/plugins → ?route=plugins
```
`cms/router.php` of `.htaccess` zet `/admin/<route>` om naar `?route=<route>`.
### Route access control (RBAC)
Elke route wordt gecontroleerd via `AdminAuth::hasPermission($route)`:
- `admin` rol heeft wildcard `*` toegang
- Andere rollen hebben een expliciete lijst van toegestane routes in `ROLE_PERMISSIONS`
- Onbevoegde routes geven een **403 error**
## Plugin admin routing
Systeem plugins kunnen admin routes registreren. Deze worden afgehandeld door `PluginManager::handleAdminRoute($route)`:
1. Systeem plugin registreert routes via `getAdminRoutes()`
2. `PluginManager::getAdminMenuItems()` verzamelt admin menu items via `getAdminMenu()`
3. Bij een admin request zoekt `PluginManager::handleAdminRoute($route)` een plugin die de route afhandelt
4. De plugin methode `handleAdminRoute($route)` rendert de pagina inhoud
```php
// Routes: /admin/dashboard, /admin/content, etc.
// Query parameter: ?route=dashboard
// PluginManager roept deze aan voor /admin/mijn-systeem
$plugin->handleAdminRoute('mijn-systeem');
```