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 c2bcd7be22
commit b38be8366c
35 changed files with 1493 additions and 255 deletions
+8 -8
View File
@@ -2,14 +2,14 @@
The admin manager guide contains the following topics: The admin manager guide contains the following topics:
- **Dashboard** - Website overview - **Dashboard** - Role-based overview of the website (Admin, Content Manager, BI Manager, Site Admin)
- **Content management** - Managing files and pages - **Content management** - Managing files and pages with layout selection and plugins
- **Configuration** - Site settings - **Configuration** - Site settings (title, language, author, analytics, logging)
- **Theme management** - Managing and creating themes - **Theme management** - Managing, activating and creating themes (SCSS compilation)
- **Security** - Bot protection and sessions - **Security** - Bot protection, rate limiting and session settings
- **Plugins** - Managing and creating plugins - **Plugins** - Managing plugins: content (sidebar) and system (admin menu/API)
- **Users** - Adding and removing users - **Users** - User management with roles (Admin, Content Manager, BI Manager, Site Admin)
- **Statistics** - Viewing visitor statistics - **Statistics** - Viewing and exporting visitor statistics
- **Logs** - Viewing and filtering log files - **Logs** - Viewing and filtering log files
Select a topic from the navigation on the left. Select a topic from the navigation on the left.
+40 -11
View File
@@ -2,16 +2,45 @@
## Managing files ## Managing files
- **Upload** - Upload media files - **New folder** — Create folder structure
- **New folder** - Create folder structure - **New file** Create a page (`.md`, `.php`, `.html`)
- **New file** - Create a page - **Edit** — Modify existing content in the CodeMirror editor
- **Edit** - Modify existing content - **Rename** — Change file or folder names
- **Rename** - Change file names - **Move** — Move content to another folder
- **Move** - Move content - **Delete** — Remove content
- **Delete** - Remove content - **Rename folder** — Change a folder name
## Editor ## Editor (content-edit)
- CodeMirror with syntax highlighting - **CodeMirror** with syntax highlighting (Markdown, PHP, HTML)
- Toolbar for Markdown formatting - **Toolbar** for quickly inserting Markdown
- Shortcuts: Ctrl+S (save), Ctrl+N (new) - **Shortcuts**: Ctrl+S (save), Ctrl+N (new)
## Layout selection
On the content-edit page you can choose the layout from the layouts defined in `theme.json` (template mapping). The selected layout is stored in the frontmatter `layout:` key.
## Plugins on pages
- Content plugins (from `plugin.json` with `type: "content"`) appear in the plugin selection
- Choose which plugins appear in the sidebar
- **Order is adjustable** with up/down buttons
- The plugin order is stored in the frontmatter `plugins:` key
- Plugins are **hidden** when the chosen layout has no sidebar (e.g. `full_content`)
## Frontmatter
The editor updates the frontmatter live when layout or plugin selection changes:
```markdown
---
layout: left_sidebar
plugins:
- HTMLBlock
- Navigation
---
# Page title
Content...
```
+26 -4
View File
@@ -1,10 +1,32 @@
# Dashboard # Dashboard
The dashboard shows an overview of: The dashboard shows a **role-based overview** of the website. Which widgets are visible depends on the role of the logged-in user.
- Views (30 days) ## Roles and widgets
- Unique visitors
### Admin
- Views (30 days) and unique visitors
- Number of pages and folders - Number of pages and folders
- Active plugins - Active plugins
- Recent activity - Recent activity
- Quick actions - System information
- Quick actions (new page, plugin, theme)
### Content Manager
- Number of pages and folders
- Recent content changes
- Quick actions (new page, folder)
### BI Manager
- Views (30 days) and unique visitors
- Top pages
- Recent visits
### Site Admin
- Active plugins and themes
- System information
- Quick actions (theme, plugin, update)
## Access
The dashboard is the default page after login (`/admin/dashboard`). All roles have access to the dashboard.
+33 -6
View File
@@ -1,13 +1,40 @@
# Users # Users
## Add user Users are stored in `admin/config/admin.json` (file-based, no database). Each user has a **role** that determines which admin routes and sidebar items are visible.
## Roles
CodePress has four roles, defined in `AdminAuth::ROLE_PERMISSIONS`:
| Role | Label | Permissions |
|------|-------|-------------|
| `admin` | Admin | Everything (`*`) |
| `content-manager` | Content Manager | Content management, guide |
| `bi-manager` | BI Manager | Statistics, logs, guide |
| `site-admin` | Site Admin | Theme, plugins, statistics, logs, update, guide |
Roles are displayed with their label via `AdminAuth::ROLE_LABELS`.
## Adding a user
1. Go to **Users** 1. Go to **Users**
2. Enter username 2. Enter username
3. Choose password 3. Choose password (stored as bcrypt hash)
4. Click **Add** 4. Select a role
5. Click **Add**
## Delete user ## Editing a user
- Cannot delete own account - Change password (new bcrypt hash)
- Confirm with password - Change role (immediately affects visible routes and sidebar items)
## Deleting a user
- Not possible for own account
- Confirm with password
## Access control
- Route access is checked in `public/admin.php` via `AdminAuth::hasPermission()`
- Unauthorized routes return a **403 error**
- Sidebar items are conditionally shown via the `has_permission()` Twig function in `admin.twig`
+42 -8
View File
@@ -1,15 +1,49 @@
# Plugins # Plugins
## Plugin types
CodePress has two kinds of plugins, determined by the `type` field in `plugin.json`:
- **Content plugins** (`type: "content"`) — Appear in the sidebar and in the plugin selection on content-edit pages. Provide sidebar content via `getSidebarContent()`.
- **System plugins** (`type: "system"`) — Are loaded by PluginManager but do NOT appear in the sidebar. Provide functionality via admin menu, routes and the CMSAPI. Registered via `getAdminMenu()` and `getAdminRoutes()`.
When no `type` field is present, `content` is assumed.
## Essential plugins
Essential plugins are defined in `getProtectedPlugins()` in `public/admin.php`. Current essential plugin: **Navigation**.
These plugins:
- Cannot be deactivated
- Cannot be edited
- Cannot be deleted
On the plugins page they get an **Essential** badge instead of the action buttons.
## Managing plugins ## Managing plugins
- **Enable/Disable** - Turn plugins on/off - **Activate/Deactivate** Turn a plugin on/off (not for essential plugins)
- **Edit** - Modify plugin code - **Edit** Modify plugin code in CodeMirror (not for essential plugins)
- **Configuration** - Plugin settings - **Configuration** — Edit plugin settings
- **Delete** - Remove plugin - **Delete** Remove the plugin folder (not for essential plugins)
## New plugin The admin plugins page shows a **Content** or **System** badge per plugin.
## Creating a new plugin
1. Go to **Plugins****New plugin** 1. Go to **Plugins****New plugin**
2. Enter a name (e.g. `MyPlugin`) 2. Enter a name (e.g. `MyPlugin`) — this becomes the folder name
3. Edit `plugin.php` 3. Choose the type: **Content** or **System**
4. Enable the plugin 4. The file `MyPlugin.php` is created (NOT `plugin.php`)
5. Edit the plugin code in CodeMirror
6. Activate the plugin
## Plugin filename
Plugin PHP files are named `<PluginName>.php` (e.g. `Navigation.php`, `HTMLBlock.php`). `PluginManager` loads `$pluginDir . '/' . $pluginName . '.php'`.
## Plugin CSS
- Content and system plugins can have their own CSS in `assets/scss/` and `assets/css/`
- Plugin CSS is automatically loaded after theme CSS (in `base.twig`), so themes can override plugin styling
- Plugin assets are served via `cms/router.php` at URL `/plugins/<Name>/assets/...`
+57 -12
View File
@@ -2,20 +2,65 @@
## Managing themes ## Managing themes
1. Go to **Theme** in admin menu 1. Go to **Theme** in the admin menu
2. **Activate** - Choose active theme 2. **Activate** Choose the active theme (stored in `config.json`)
3. **Compile SCSS** - Process SCSS to CSS 3. **Compile SCSS** Process SCSS to CSS (forced)
4. **New theme** - Create custom theme 4. **New theme** Create a custom theme via admin or manually
## Theme structure ## Theme structure
``` ```
themes/default/ themes/default/
├── theme.json # Theme configuration ├── theme.json # { title, config.default_template, template: layout→.twig }
├── base.twig # Main layout ├── base.twig # Main layout (head, header, nav, breadcrumb, footer)
├── full_content.twig # Layouts ├── full_content.twig # Layout: full width
├── left_sidebar.twig ├── left_sidebar.twig # Layout: sidebar on the left
├── right_sidebar.twig ├── right_sidebar.twig # Layout: sidebar on the right
├── partials/ # Header, nav, footer ├── custom1.twig # Layout: custom
── assets/ # CSS, JS, images ── guide.twig # Layout: guide with sidebar (Navigation plugin)
``` ├── partials/ # header.twig, navigation.twig, footer.twig
└── assets/
├── scss/theme.scss # SCSS source (only CSS source — manual css/theme.css must not exist)
├── css_compiled/ # Generated by scssphp (read-only, do not edit manually)
├── css/ # External CSS (bootstrap.min.css, bootstrap-icons.css, mobile.css)
├── js/ # app.js, bootstrap.bundle.min.js
├── fonts/ # bootstrap-icons.woff, woff2
└── img/ # favicon, icon, world-map
```
## theme.json
```json
{
"title": "default",
"config": {
"default_template": "full_content"
},
"template": {
"full_content": "full_content.twig",
"left_sidebar": "left_sidebar.twig",
"right_sidebar": "right_sidebar.twig",
"custom1": "custom1.twig",
"guide": "guide.twig"
}
}
```
- `title` — Display name in admin
- `config.default_template` — Default layout for pages without a `layout:` frontmatter
- `template` — Mapping from layout name to `.twig` file
## SCSS compilation
- `ThemeManager` compiles `assets/scss/theme.scss` at runtime to `assets/css_compiled/theme.css` via scssphp
- `css_compiled/` is **read-only** — do not edit manually
- `assets/css/theme.css` must **not** exist; otherwise `ThemeManager::getCssUrl()` ignores the SCSS
- After SCSS changes: remove `assets/css_compiled/theme.css` and `.mtime` to force recompilation
## Layouts
Layouts are chosen via the frontmatter `layout:` key in content files. Unknown layouts fall back to `config.default_template` from `theme.json`.
## guide.twig
Special layout for guides. Injects the Navigation plugin into the sidebar for sidebar navigation. Automatically used for pages in the `guide/` folder.
+15 -8
View File
@@ -2,13 +2,20 @@
The CodePress developer guide contains the following topics: The CodePress developer guide contains the following topics:
- **Architecture** - CMS architecture and folder structure - **Architecture** CMS architecture and folder structure
- **Core classes** - CodePressCMS, ThemeManager, PluginManager - **Core classes** CodePressCMS, ThemeManager, PluginManager, AdminAuth
- **Plugin development** - Developing plugins - **Plugin development** — Plugin types (content/system), structure, API
- **Routing** - Frontend and admin routing - **Routing** Frontend, admin and plugin admin routing
- **Security** - XSS, CSRF, path traversal - **Security** XSS, CSRF, path traversal, RBAC
- **Testing** - Penetration, accessibility and functional tests - **Testing** Penetration, accessibility and functional tests
- **Debugging** - Logging and cache - **Debugging** Logging and cache
- **Performance** - OPcache and SCSS caching - **Performance** OPcache and SCSS caching
Important concepts in CodePress 2.5.2:
- **Plugin types** — Content plugins (sidebar) and system plugins (admin menu, routes, API)
- **Admin plugin API** — System plugins can register admin menu items and routes
- **SCSS compilation** — `ThemeManager` compiles SCSS to `css_compiled/` via scssphp (read-only)
- **Asset serving** — `public/asset.php` serves themes/, admin/assets/ and plugins/ on Apache (instead of PHP dev router)
Select a topic from the navigation on the left. Select a topic from the navigation on the left.
+80 -7
View File
@@ -1,11 +1,84 @@
# CMS Architecture # CMS Architecture
CodePress is a file-based CMS without a database. Content, configuration and users are stored in files.
## Folder structure
``` ```
codepress/ codepress/
├── cms/core/ # Core engine ├── cms/ # Core CMS engine
├── admin/ # Admin console │ ├── core/
├── themes/ # Themes │ │ ├── class/
├── plugins/ # Plugins │ │ │ ├── CodePressCMS.php # Main CMS class (routing, rendering, breadcrumb)
├── content/ # Content │ │ │ ├── ThemeManager.php # Theme resolver + Twig render + SCSS compile
└── public/ # Web root │ │ │ ├── ContentAPI.php # Read-only API for PHP content
``` │ │ │ ├── ContentSecurityPolicy.php # CSP header management
│ │ │ ├── Analytics.php # Visitor statistics
│ │ │ ├── BotGuard.php # Bot/AI detection
│ │ │ ├── Cache.php # Cache system
│ │ │ ├── GeoIP.php # GeoIP lookup (country, flag)
│ │ │ ├── Logger.php # Basic logging
│ │ │ ├── LogManager.php # Dynamic logging (SQLite/syslog)
│ │ │ ├── RateLimiter.php # Rate limiting per IP
│ │ │ ├── RequestLogger.php # Request logging + visitor info
│ │ │ ├── SearchEngine.php # Full text search
│ │ │ └── AccessibilityManager.php # Accessibility features
│ │ ├── plugin/
│ │ │ ├── PluginManager.php # Plugin loader (hooks, filters, sidebar, admin routes)
│ │ │ └── CMSAPI.php # API for plugins (getPage, getConfig, etc.)
│ │ ├── config.php # Config loader (reads config.json)
│ │ └── index.php # Bootstrap (autoloader, requires)
│ ├── lang/ # Language files (nl.php, en.php)
│ └── router.php # PHP dev server router
├── themes/ # Dynamic themes
│ └── default/ # Default theme (views + assets)
│ ├── theme.json # { title, config.default_template, template: layout→.twig }
│ ├── base.twig # Main layout
│ ├── *.twig # Layout templates
│ ├── partials/ # header.twig, navigation.twig, footer.twig
│ └── assets/
│ ├── scss/theme.scss # SCSS source (only CSS source)
│ ├── css_compiled/ # Generated by scssphp (read-only)
│ ├── css/ # External CSS (bootstrap.min.css, etc.)
│ ├── js/ # JavaScript
│ └── img/ # Images
├── admin/ # Admin panel
│ ├── config/
│ │ ├── app.php # Admin app configuration
│ │ └── admin.json # Users & security (file-based, .gitignore'd)
│ ├── src/
│ │ └── AdminAuth.php # Authentication + RBAC
│ ├── theme/default/ # Admin theme (views + assets)
│ │ ├── theme.json
│ │ ├── assets/ # CSS, JS, CodeMirror, fonts
│ │ └── views/ # login.twig, layouts/, pages/
│ └── storage/ # Logs, cache, geoip
├── plugins/ # CMS plugins
│ ├── Navigation/ # Essential navigation plugin (protected)
│ │ ├── Navigation.php # Plugin code (NOT plugin.php)
│ │ ├── plugin.json # Metadata with type field
│ │ └── assets/ # SCSS + CSS
│ └── HTMLBlock/ # Example sidebar plugin
├── content/ # Website content (.md, .php, .html) — .gitignore'd
├── guide/ # Guides (nl/en)
├── public/ # Web root
│ ├── index.php # Website entry point
│ ├── admin.php # Admin entry point + routing
│ ├── asset.php # Asset server for Apache (themes/, admin/assets/, plugins/)
│ ├── .htaccess # Forwards asset URLs to asset.php
│ ├── favicon.ico
│ └── robots.txt
├── var/ # Cache (twig) — .gitignore'd
├── config.json # Site configuration — .gitignore'd
├── composer.json # PHP dependencies (CommonMark, Twig, scssphp)
└── version.php # Version information (2.5.2)
```
## Principles
- **No database** — Everything in files (content in `content/`, users in `admin/config/admin.json`, config in `config.json`)
- **File-based auth** — `AdminAuth` uses bcrypt hashes in `admin.json`, sessions for login
- **Twig templating** — Themes use Twig; `ThemeManager` renders via Twig
- **SCSS compilation** — `assets/scss/theme.scss``assets/css_compiled/theme.css` via scssphp (read-only output)
- **Plugin system** — `PluginManager` loads content and system plugins with hooks/filters
- **Asset serving** — PHP dev router (`cms/router.php`) or Apache (`.htaccess``public/asset.php`)
+81 -4
View File
@@ -10,6 +10,13 @@ $cms->init();
$cms->renderPage($pagePath); $cms->renderPage($pagePath);
``` ```
Responsibilities:
- Routing and page rendering
- Breadcrumb generation (dynamic: Home > [subfolders] > [page])
- Loading guide pages (`getGuidePage()`)
- Title extraction from H1 (`getTitleFromFile()`)
- Display name processing (`formatDisplayName()`)
## ThemeManager.php ## ThemeManager.php
Theme management in `cms/core/class/ThemeManager.php`: Theme management in `cms/core/class/ThemeManager.php`:
@@ -19,14 +26,84 @@ $themeManager = new ThemeManager($config);
$themeManager->getActiveTheme(); $themeManager->getActiveTheme();
$themeManager->renderTwig($template, $data); $themeManager->renderTwig($template, $data);
$themeManager->compileCss($force); $themeManager->compileCss($force);
$themeManager->getCssUrl();
``` ```
Responsibilities:
- Resolving the active theme from `config.json`
- Loading `theme.json` (title, config.default_template, template mapping)
- Building the Twig environment (rooted in the theme folder)
- **SCSS compilation** — compiles `assets/scss/theme.scss` to `assets/css_compiled/theme.css` via scssphp
- Resolving the layout to a `.twig` template (fallback to `config.default_template`)
`getCssUrl()` priority: 1) `assets/css/theme.css` (manual), 2) `assets/css_compiled/theme.css` (compiled).
## PluginManager.php ## PluginManager.php
Plugin system in `cms/core/class/PluginManager.php`: Plugin system in `cms/core/plugin/PluginManager.php`:
```php ```php
$pluginManager = new PluginManager(); $pluginManager = new PluginManager($pluginsPath, $enabledPlugins);
$pluginManager->loadPlugins($enabledPlugins); $pluginManager->getSidebarContent($allowedPlugins);
$pluginManager->getPluginCssUrls();
$pluginManager->executeHook($name, $params); $pluginManager->executeHook($name, $params);
``` $pluginManager->getAdminMenuItems();
$pluginManager->handleAdminRoute($route);
$pluginManager->getPluginType($pluginName);
```
Responsibilities:
- Loading plugins from `plugins/` folders (only enabled plugins)
- Plugin file: `<PluginName>.php` (NOT `plugin.php`)
- Hooks and filters system (`doAction`, `applyFilters`)
- Collecting sidebar content from content plugins (`getSidebarContent`)
- Collecting plugin CSS URLs (`getPluginCssUrls`)
- **Admin menu items** from system plugins (`getAdminMenuItems`)
- **Admin routes** handled via system plugins (`handleAdminRoute`)
- Determining the **plugin type** (`getPluginType``content` or `system`)
- `isPluginViewable` — system plugins do not appear in the sidebar
## AdminAuth.php
Authentication and RBAC in `admin/src/AdminAuth.php`:
```php
$auth = new AdminAuth($appConfig);
$auth->login($username, $password);
$auth->logout();
$auth->hasPermission($route);
$auth->verifyCsrf($token);
```
Constants:
- `ROLE_PERMISSIONS` — Mapping of role → allowed route prefixes. `admin` has wildcard `*`.
- `ROLE_LABELS` — Human-readable labels per role.
Roles:
| Role | Label | Permissions |
|------|-------|-------------|
| `admin` | Admin | Everything (`*`) |
| `content-manager` | Content Manager | Content management, guide |
| `bi-manager` | BI Manager | Statistics, logs, guide |
| `site-admin` | Site Admin | Theme, plugins, statistics, logs, update, guide |
Responsibilities:
- Session-based authentication
- bcrypt password hashing
- CSRF tokens (`verifyCsrf`)
- Brute-force lockout (login attempts tracking)
- RBAC via `hasPermission($route)` — checks the route against `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();
```
Provides read-only access for plugins to CMS data (config, pages, content).
@@ -1,43 +1,144 @@
# Plugin Development # Plugin Development
## Plugin types
CodePress has two kinds of plugins, determined by the `type` field in `plugin.json`:
- **Content plugins** (`type: "content"`) — Appear in the sidebar and in the plugin selection on content-edit pages. Provide sidebar content via `getSidebarContent()`.
- **System plugins** (`type: "system"`) — Are loaded by PluginManager but do NOT appear in the sidebar. Provide functionality via admin menu, routes and the CMSAPI.
When no `type` field is present, `content` is assumed.
## Plugin structure ## Plugin structure
``` ```
plugins/MyPlugin/ plugins/MyPlugin/
├── plugin.json # Plugin metadata ├── MyPlugin.php # Plugin code (NOT plugin.php)
├── plugin.php # Plugin code ├── plugin.json # Metadata with type field
── config.json # Optional configuration ── config.json # Optional configuration
└── assets/
├── scss/myplugin.scss # SCSS source (optional)
└── css/myplugin.css # CSS (manually maintained)
``` ```
Plugin files are named `<PluginName>.php` (e.g. `Navigation.php`, `HTMLBlock.php`). `PluginManager` loads `$pluginDir . '/' . $pluginName . '.php'`.
## plugin.json ## plugin.json
```json ```json
{ {
"name": "My Plugin", "name": "My Plugin",
"version": "1.0.0", "version": "1.0.0",
"author": "Your Name", "author": "Your Name",
"description": "Description" "description": "Description",
"type": "content"
} }
``` ```
## plugin.php example - `name` — Display name
- `type``"content"` or `"system"` (default: `content`)
## Content plugin example
```php ```php
<?php <?php
/** /**
* Plugin: MyPlugin * Plugin: MyPlugin (content)
*/ */
class MyPlugin
{
public function getConfig(): array
{
return [
'title' => 'My Plugin',
'type' => 'content',
];
}
echo '<div class="my-plugin">Hello World</div>'; public function getSidebarContent(): string
{
return '<p>Hello World</p>';
}
}
``` ```
## System plugin example
```php
<?php
/**
* Plugin: MySystem (system)
*/
class MySystem
{
public function getConfig(): array
{
return [
'title' => 'My System',
'type' => 'system',
];
}
public function getAdminMenu(): array
{
return [
['label' => 'My System', 'route' => 'my-system', 'icon' => 'bi-gear'],
];
}
public function getAdminRoutes(): array
{
return ['my-system'];
}
public function handleAdminRoute(string $route): void
{
echo '<h1>My System page</h1>';
}
}
```
System plugins are shown in the admin sidebar via `PluginManager::getAdminMenuItems()` and handled via `PluginManager::handleAdminRoute()`.
## Using CMSAPI ## Using CMSAPI
```php ```php
<?php <?php
require_once '../../cms/core/class/PluginManager.php';
$api = PluginManager::getAPI(); $api = PluginManager::getAPI();
$config = $api->getConfig(); $config = $api->getConfig();
$content = $api->getContent(); $page = $api->getPage($path);
``` ```
`setAPI()` is called automatically by `PluginManager` if the plugin has the method.
## Plugin CSS
- Plugin CSS in `assets/css/` is manually maintained (SCSS compilation for plugins is not yet automatic)
- Plugin CSS is automatically loaded after theme CSS (in `base.twig`), so themes can override plugin styling
- Plugin assets are served via `cms/router.php` at URL `/plugins/<Name>/assets/...`
- Implement `getCssUrl()` in the plugin class to return the CSS URL
```php
public function getCssUrl(): string
{
return '/plugins/MyPlugin/assets/css/myplugin.css';
}
```
## Hooks and filters
PluginManager auto-registers these methods as hooks/filters:
- **Hooks**: `onPageLoad`, `onBeforeRender`, `onAfterRender`, `onSearch`, `onMenuBuild`
- **Filters**: `onContentFilter`, `onTitleFilter`, `onMenuFilter`
```php
public function onPageLoad($page) { /* ... */ }
public function onContentFilter($content) { return $content; }
```
## Essential plugins
Essential plugins are defined in `getProtectedPlugins()` in `public/admin.php`. Current essential plugin: **Navigation**.
These plugins cannot be deactivated, edited or deleted. Always add the `isProtectedPlugin()` check to new plugin handlers.
+49 -7
View File
@@ -2,18 +2,60 @@
## Frontend routing ## Frontend routing
Via `cms/router.php` for PHP dev server: Frontend routing goes through `cms/router.php` (PHP dev server) or `.htaccess` (Apache). Both provide clean URLs.
```php ### PHP dev server
// Clean URLs: /nl/page
// Query: ?page=page&lang=nl Start the server with:
```bash
php -S localhost:8080 cms/router.php
``` ```
`cms/router.php` serves:
- Clean URLs: `/nl/page``public/index.php?page=page&lang=nl`
- `themes/` assets
- `admin/assets/` assets
- `plugins/` assets
### Apache (live server)
`public/.htaccess` rewrites URLs to `public/index.php`. Asset URLs (`/themes/`, `/admin/assets/`, `/plugins/`) are forwarded to `public/asset.php`.
`public/asset.php` serves files from the correct folders with the correct MIME type:
- `/themes/<name>/assets/...``themes/<name>/assets/...`
- `/admin/assets/...``admin/theme/default/assets/...`
- `/plugins/<name>/assets/...``plugins/<name>/assets/...`
## Admin routing ## Admin routing
Via `public/admin.php`: Admin routing goes through `public/admin.php` with clean URLs:
```
/admin/dashboard → ?route=dashboard
/admin/content → ?route=content
/admin/plugins → ?route=plugins
```
`cms/router.php` or `.htaccess` converts `/admin/<route>` to `?route=<route>`.
### Route access control (RBAC)
Each route is checked via `AdminAuth::hasPermission($route)`:
- The `admin` role has wildcard `*` access
- Other roles have an explicit list of allowed routes in `ROLE_PERMISSIONS`
- Unauthorized routes return a **403 error**
## Plugin admin routing
System plugins can register admin routes. These are handled by `PluginManager::handleAdminRoute($route)`:
1. The system plugin registers routes via `getAdminRoutes()`
2. `PluginManager::getAdminMenuItems()` collects admin menu items via `getAdminMenu()`
3. On an admin request `PluginManager::handleAdminRoute($route)` finds a plugin that handles the route
4. The plugin method `handleAdminRoute($route)` renders the page content
```php ```php
// Routes: /admin/dashboard, /admin/content, etc. // PluginManager calls this for /admin/my-system
// Query parameter: ?route=dashboard $plugin->handleAdminRoute('my-system');
``` ```
@@ -4,28 +4,48 @@ Content is stored in the `content/` folder without a database.
## Supported file formats ## Supported file formats
- `.md` - Markdown (recommended) - `.md` Markdown (recommended)
- `.php` - Dynamic PHP pages - `.php` Dynamic PHP pages
- `.html` - Static HTML pages - `.html` Static HTML pages
## File name conventions ## File name conventions
``` ```
en.page-name.md # English page nl.pagina-naam.md # Dutch page
nl.pagina-naam.md # Dutch page en.page-name.md # English page
nl.folder/ # Dutch folder (requires an index file to be clickable)
``` ```
The language prefix is dynamically removed based on available languages via `getAvailableLanguages()`.
## Frontmatter ## Frontmatter
Markdown files can contain frontmatter metadata: Markdown files can contain frontmatter metadata:
```markdown ```markdown
--- ---
layout: full_content layout: left_sidebar
plugins: HTMLBlock plugins:
- HTMLBlock
- Navigation
--- ---
# Page title # Page title
Content... Content...
``` ```
## Frontmatter fields
- `layout` — Layout name (must exist in the `theme.json` template mapping; fallback to `config.default_template`)
- `plugins` — List of content plugins that appear in the sidebar
### plugins field
The `plugins` field determines:
- **Which plugins** appear in the sidebar (only content plugins, not system plugins)
- **The order** of the plugins in the sidebar (top to bottom)
The order in the frontmatter is the order in which the plugins are shown. In the admin content-edit page you can adjust the order with up/down buttons; the frontmatter is updated live.
Plugins are not shown when the chosen layout has no sidebar (e.g. `full_content`).
+36 -4
View File
@@ -5,12 +5,44 @@
1. Login at `/admin` 1. Login at `/admin`
2. Go to **Content** 2. Go to **Content**
3. Choose a folder or create a new page 3. Choose a folder or create a new page
4. Edit content in the editor 4. Edit content in the CodeMirror editor
5. Save with Ctrl+S 5. Save with Ctrl+S
## Editor features ## Editor features
- **CodeMirror** editor with syntax highlighting - **CodeMirror** editor with syntax highlighting (Markdown, PHP, HTML)
- **Toolbar** for quick Markdown insertion - **Toolbar** for quick Markdown insertion
- **Live preview** via button - **Shortcuts**: Ctrl+S (save), Ctrl+N (new)
- **Auto-save** backups in `.bak/` folder - **Auto-save** backups in `.bak/` folder
## Layout selection
On the content-edit page you can choose the layout from the layouts defined in `theme.json` (template mapping). The selected layout is stored in the frontmatter `layout:` key.
```markdown
---
layout: left_sidebar
---
```
Unknown layouts fall back to `config.default_template` from `theme.json`.
## Plugin selection and order
On the content-edit page you can choose content plugins for the sidebar:
- **Selection** — Only content plugins (from `plugin.json` with `type: "content"`) appear in the plugin selection
- **Order** — Adjust the order with up/down buttons
- **Frontmatter update** — The frontmatter `plugins:` key is updated live on changes
- **Layout without sidebar** — Plugins are hidden when the chosen layout has no sidebar (e.g. `full_content`)
```markdown
---
layout: left_sidebar
plugins:
- HTMLBlock
- Navigation
---
```
The order in the frontmatter determines the order of the plugins in the sidebar (top to bottom).
+9
View File
@@ -1,3 +1,12 @@
# Manual # Manual
Welcome to the CodePress CMS manual (version 2.5.2). CodePress is a file-based CMS without a database — content, configuration and users are stored in files.
The manual is divided into four sections:
- **Admin Manager** — Managing the website: dashboard, content, configuration, themes, security, plugins (content and system), users with roles, statistics and logs
- **Content Manager** — Managing content: structure, managing pages (layout selection, plugin order), media and the Content API
- **Theme Developer** — Developing themes: structure, `theme.json`, Twig templates, SCSS styling (only CSS source), layouts and new themes
- **CodePress Developer** — Core development: architecture, core classes, plugin development (content/system), routing, security (RBAC), testing, debugging and performance
Select a topic from the navigation on the left. Select a topic from the navigation on the left.
+1 -1
View File
@@ -3,7 +3,7 @@
The theme developer guide contains the following topics: The theme developer guide contains the following topics:
- **Theme structure** - Folder structure of a theme - **Theme structure** - Folder structure of a theme
- **theme.json** - Theme configuration - **theme.json** - Configuration of a theme
- **Twig templates** - Twig syntax, variables and blocks - **Twig templates** - Twig syntax, variables and blocks
- **SCSS styling** - Compiling and writing SCSS - **SCSS styling** - Compiling and writing SCSS
- **Layouts** - Defining and using layouts - **Layouts** - Defining and using layouts
+54 -8
View File
@@ -1,5 +1,7 @@
# Layouts # Layouts
Layouts define the page structure (left sidebar, full width, etc.). Layouts are defined in `theme.json` and chosen via frontmatter in content files.
## Choosing a layout in content ## Choosing a layout in content
```markdown ```markdown
@@ -14,14 +16,58 @@ Content...
## Layouts in theme.json ## Layouts in theme.json
Layouts are defined in the `template` mapping. The `config.default_template` is the fallback for pages without a `layout:` frontmatter or with an unknown layout:
```json ```json
{ {
"default_layout": "full_content", "config": {
"layouts": { "default_template": "full_content"
"full_content": "full_content.twig", },
"left_sidebar": "left_sidebar.twig", "template": {
"right_sidebar": "right_sidebar.twig", "full_content": "full_content.twig",
"custom1": "custom1.twig" "left_sidebar": "left_sidebar.twig",
} "right_sidebar": "right_sidebar.twig",
"custom1": "custom1.twig",
"guide": "guide.twig"
}
} }
``` ```
## Layout template
A layout template extends `base.twig` and fills the `content` block:
```twig
{% extends 'base.twig' %}
{% block content %}
<div class="container">
{{ content|raw }}
</div>
{% endblock %}
```
## Layouts with sidebar
Layouts with a sidebar can show plugin content:
```twig
{% extends 'base.twig' %}
{% block content %}
<div class="row">
<main class="col-md-8">
{{ content|raw }}
</main>
<aside class="col-md-4">
{{ sidebar_content|raw }}
</aside>
</div>
{% endblock %}
```
If a page has no plugins or the layout has no sidebar, `sidebar_content` is empty.
## Guide layout
The `guide` layout (`guide.twig`) is special for guides. It injects the Navigation plugin into the sidebar for sidebar navigation. Automatically used for pages in the `guide/` folder.
+40 -11
View File
@@ -2,20 +2,49 @@
``` ```
themes/my-theme/ themes/my-theme/
├── theme.json # Theme configuration ├── theme.json # { title, config.default_template, template: layout→.twig }
├── base.twig # Main layout ├── base.twig # Main layout (head, header, nav, breadcrumb, footer)
├── full_content.twig # Layout: full-width ├── full_content.twig # Layout: full width
├── left_sidebar.twig # Layout: left sidebar ├── left_sidebar.twig # Layout: sidebar on the left
├── right_sidebar.twig # Layout: right sidebar ├── right_sidebar.twig # Layout: sidebar on the right
├── custom.twig # Layout: custom ├── custom1.twig # Layout: custom
├── guide.twig # Layout: guide with sidebar (Navigation plugin)
├── partials/ ├── partials/
│ ├── header.twig │ ├── header.twig
│ ├── navigation.twig │ ├── navigation.twig
│ └── footer.twig │ └── footer.twig
└── assets/ └── assets/
├── scss/theme.scss # SCSS source ├── scss/theme.scss # SCSS source (the only CSS source)
├── css/ # CSS files ├── css_compiled/ # Generated by scssphp (read-only, do not edit manually)
├── js/theme.js # JavaScript ├── css/ # External CSS (bootstrap.min.css, bootstrap-icons.css, mobile.css)
├── fonts/ # Fonts ├── js/ # app.js, bootstrap.bundle.min.js
── img/ # Images ── fonts/ # bootstrap-icons.woff, woff2
└── img/ # favicon, icon, world-map
```
## SCSS is the only CSS source
- **ALWAYS** edit `assets/scss/theme.scss` — this is the only CSS source
- `ThemeManager` compiles SCSS at runtime to `assets/css_compiled/theme.css` via scssphp
- `assets/css_compiled/` is **read-only** — do not edit manually
- **NEVER** create or edit `assets/css/theme.css` manually; this file must not exist
- `ThemeManager::getCssUrl()` priority: 1) `assets/css/theme.css` (manual), 2) `assets/css_compiled/theme.css` (compiled). If `theme.css` exists, the SCSS is ignored.
- After SCSS changes: remove `assets/css_compiled/theme.css` and `.mtime` to force recompilation
```bash
rm themes/my-theme/assets/css_compiled/theme.css themes/my-theme/assets/css_compiled/.mtime
```
## guide.twig
Special layout for guides. Injects the Navigation plugin into the sidebar for sidebar navigation. Automatically used for pages in the `guide/` folder.
## Plugin CSS loading
Plugin CSS is automatically loaded after theme CSS in `base.twig`, so themes can override plugin styling:
```twig
{% for cssUrl in plugin_css_urls|default([]) %}
<link href="{{ cssUrl }}" rel="stylesheet">
{% endfor %}
``` ```
+37 -12
View File
@@ -2,20 +2,45 @@
```json ```json
{ {
"title": "My Theme", "title": "My Theme",
"default_layout": "full_content", "config": {
"header_color": "#0a369d", "default_template": "full_content"
"layouts": { },
"full_content": "full_content.twig", "template": {
"left_sidebar": "left_sidebar.twig", "full_content": "full_content.twig",
"right_sidebar": "right_sidebar.twig" "left_sidebar": "left_sidebar.twig",
} "right_sidebar": "right_sidebar.twig",
"custom1": "custom1.twig",
"guide": "guide.twig"
}
} }
``` ```
## Fields ## Fields
- `title` - Display name in admin - `title` Display name in admin
- `default_layout` - Default layout for new pages - `config.default_template` Default layout for pages without a `layout:` frontmatter (fallback for unknown layouts)
- `header_color` - Admin sidebar color - `template` — Mapping from layout name to `.twig` file
- `layouts` - Mapping of layout names to .twig files
## Template mapping
The `template` mapping defines which layouts are available. Each key is a layout name, each value is the `.twig` file:
| Layout name | Twig file | Description |
|-------------|-----------|-------------|
| `full_content` | `full_content.twig` | Full width, no sidebar |
| `left_sidebar` | `left_sidebar.twig` | Sidebar on the left |
| `right_sidebar` | `right_sidebar.twig` | Sidebar on the right |
| `custom1` | `custom1.twig` | Custom layout |
| `guide` | `guide.twig` | Guide with sidebar (Navigation plugin) |
## Layout selection
- Layouts are chosen via the frontmatter `layout:` key in content files
- Unknown layouts fall back to `config.default_template`
- `ThemeManager::getTemplates()` returns the template mapping
- `ThemeManager::getConfig()` returns the config section (including `default_template`)
## Guide layout
The `guide` layout is special for guides. `getGuidePage()` in `CodePressCMS.php` automatically injects the Navigation plugin into the metadata for sidebar navigation.
+8 -8
View File
@@ -2,14 +2,14 @@
De admin beheerder handleiding bevat de volgende onderwerpen: De admin beheerder handleiding bevat de volgende onderwerpen:
- **Dashboard** - Overzicht van de website - **Dashboard** - Role-based overzicht van de website (Admin, Content Beheerder, BI Beheerder, Site Admin)
- **Content beheer** - Bestanden en pagina's beheren - **Content beheer** - Bestanden en pagina's beheren met layout selectie en plugins
- **Configuratie** - Site instellingen - **Configuratie** - Site instellingen (titel, taal, auteur, analytics, logging)
- **Thema beheer** - Thema's beheren en aanmaken - **Thema beheer** - Thema's beheren, activeren en aanmaken (SCSS compilatie)
- **Beveiliging** - Bot bescherming en sessies - **Beveiliging** - Bot bescherming, rate limiting en sessie instellingen
- **Plugins** - Plugins beheren en aanmaken - **Plugins** - Plugins beheren: content (sidebar) en systeem (admin menu/API)
- **Gebruikers** - Gebruikers toevoegen en verwijderen - **Gebruikers** - Gebruikersbeheer met rollen (Admin, Content Beheerder, BI Beheerder, Site Admin)
- **Statistieken** - Bezoekersstatistieken bekijken - **Statistieken** - Bezoekersstatistieken bekijken en exporteren
- **Logs** - Logbestanden bekijken en filteren - **Logs** - Logbestanden bekijken en filteren
Selecteer een onderwerp uit de navigatie aan de linkerkant. Selecteer een onderwerp uit de navigatie aan de linkerkant.
+40 -11
View File
@@ -2,16 +2,45 @@
## Bestanden beheren ## Bestanden beheren
- **Uploaden** - Media bestanden uploaden - **Nieuwe map** Mappen structuur aanmaken
- **Nieuwe map** - Mappen structuur aanmaken - **Nieuw bestand** — Pagina aanmaken (`.md`, `.php`, `.html`)
- **Nieuw bestand** - Pagina aanmaken - **Bewerken** — Bestaande content wijzigen in CodeMirror editor
- **Bewerken** - Bestaande content wijzigen - **Hernoemen** Bestands- of mapnamen aanpassen
- **Hernoemen** - Bestandsnamen aanpassen - **Verplaatsen** — Content verplaatsen naar andere map
- **Verplaatsen** - Content verplaatsen - **Verwijderen** Content verwijderen
- **Verwijderen** - Content verwijderen - **Map hernoemen** — Map naam wijzigen
## Editor ## Editor (content-edit)
- CodeMirror met syntax highlighting - **CodeMirror** met syntax highlighting (Markdown, PHP, HTML)
- Toolbar voor Markdown formatting - **Toolbar** voor snel Markdown invoeren
- Sneltoetsen: Ctrl+S (opslaan), Ctrl+N (nieuw) - **Sneltoetsen**: Ctrl+S (opslaan), Ctrl+N (nieuw)
## Layout selectie
Op de content-edit pagina kun je de layout kiezen uit de layouts gedefinieerd in `theme.json` (template mapping). De geselecteerde layout wordt opgeslagen in de frontmatter `layout:` key.
## Plugins op pagina's
- Content plugins (uit `plugin.json` met `type: "content"`) verschijnen in de plugin selectie
- Kies welke plugins in de sidebar verschijnen
- **Volgorde aanpasbaar** met up/down knoppen
- De plugin volgorde wordt opgeslagen in de frontmatter `plugins:` key
- Plugins worden **verbergen** als de gekozen layout geen sidebar heeft (bijv. `full_content`)
## Frontmatter
De editor werkt de frontmatter live bij bij wijzigingen van layout of plugin selectie:
```markdown
---
layout: left_sidebar
plugins:
- HTMLBlock
- Navigation
---
# Pagina titel
Content...
```
+26 -4
View File
@@ -1,10 +1,32 @@
# Dashboard # Dashboard
Het dashboard toont een overzicht van: Het dashboard toont een **role-based overzicht** van de website. Welke widgets zichtbaar zijn, hangt af van de rol van de ingelogde gebruiker.
- Weergaven (30 dagen) ## Rollen en widgets
- Unieke bezoekers
### Admin
- Weergaven (30 dagen) en unieke bezoekers
- Aantal pagina's en mappen - Aantal pagina's en mappen
- Actieve plugins - Actieve plugins
- Recente activiteit - Recente activiteit
- Snelle acties - Systeem informatie
- Snelle acties (nieuwe pagina, plugin, thema)
### Content Beheerder
- Aantal pagina's en mappen
- Recente content wijzigingen
- Snelle acties (nieuwe pagina, map)
### BI Beheerder
- Weergaven (30 dagen) en unieke bezoekers
- Top pagina's
- Recente bezoeken
### Site Admin
- Actieve plugins en thema's
- Systeem informatie
- Snelle acties (thema, plugin, update)
## Toegang
Het dashboard is de standaard pagina na login (`/admin/dashboard`). Alle rollen hebben toegang tot het dashboard.
+30 -3
View File
@@ -1,13 +1,40 @@
# Gebruikers # Gebruikers
Gebruikers worden opgeslagen in `admin/config/admin.json` (file-based, geen database). Elke gebruiker heeft een **rol** die bepaalt welke admin routes en sidebar items zichtbaar zijn.
## Rollen
CodePress kent vier rollen, gedefinieerd in `AdminAuth::ROLE_PERMISSIONS`:
| 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 |
Rollen worden getoond met hun label via `AdminAuth::ROLE_LABELS`.
## Gebruiker toevoegen ## Gebruiker toevoegen
1. Ga naar **Gebruikers** 1. Ga naar **Gebruikers**
2. Vul gebruikersnaam in 2. Vul gebruikersnaam in
3. Kies wachtwoord 3. Kies wachtwoord (opgeslagen als bcrypt hash)
4. Klik **Toevoegen** 4. Selecteer een rol
5. Klik **Toevoegen**
## Gebruiker bewerken
- Wachtwoord wijzigen (nieuwe bcrypt hash)
- Rol wijzigen (beïnvloedt direct zichtbare routes en sidebar items)
## Gebruiker verwijderen ## Gebruiker verwijderen
- Kan niet voor eigen account - Kan niet voor eigen account
- Bevestig met wachtwoord - Bevestig met wachtwoord
## Toegangscontrole
- Route access wordt gecontroleerd in `public/admin.php` via `AdminAuth::hasPermission()`
- Onbevoegde routes geven een **403 error**
- Sidebar items worden conditioneel getoond via de `has_permission()` Twig function in `admin.twig`
+42 -8
View File
@@ -1,15 +1,49 @@
# Plugins # Plugins
## 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. Geregistreerd via `getAdminMenu()` en `getAdminRoutes()`.
Bij afwezigheid van een `type` veld wordt `content` aangenomen.
## 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
- Kunnen NIET worden bewerkt
- Kunnen NIET worden verwijderd
Op de plugins pagina krijgen ze een **Essentieel** badge i.p.v. de actieknoppen.
## Plugins beheren ## Plugins beheren
- **Activeren/Deactiveren** - Plugins aan/uit - **Activeren/Deactiveren** Plugin aan/uit zetten (niet voor essentiële plugins)
- **Bewerken** - Plugin code aanpassen - **Bewerken** Plugin code aanpassen in CodeMirror (niet voor essentiële plugins)
- **Configuratie** - Plugin instellingen - **Configuratie** Plugin instellingen bewerken
- **Verwijderen** - Plugin verwijderen - **Verwijderen** Plugin map verwijderen (niet voor essentiële plugins)
## Nieuwe plugin De admin plugins pagina toont een **Content** of **Systeem** badge per plugin.
## Nieuwe plugin aanmaken
1. Ga naar **Plugins****Nieuwe plugin** 1. Ga naar **Plugins****Nieuwe plugin**
2. Geef naam op (bijv. `MijnPlugin`) 2. Geef naam op (bijv. `MijnPlugin`) — dit wordt de mapnaam
3. Bewerk `plugin.php` 3. Kies het type: **Content** of **Systeem**
4. Activeer de plugin 4. Het bestand `MijnPlugin.php` wordt aangemaakt (NIET `plugin.php`)
5. Bewerk de plugin code in CodeMirror
6. Activeer de plugin
## Plugin bestandsnaam
Plugin PHP bestanden heten `<PluginName>.php` (bijv. `Navigation.php`, `HTMLBlock.php`). `PluginManager` laadt `$pluginDir . '/' . $pluginName . '.php'`.
## Plugin CSS
- Content en systeem plugins kunnen eigen CSS hebben in `assets/scss/` en `assets/css/`
- 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/...`
+56 -9
View File
@@ -3,17 +3,64 @@
## Thema's beheren ## Thema's beheren
1. Ga naar **Thema** in admin menu 1. Ga naar **Thema** in admin menu
2. **Activeren** - Kies actief thema 2. **Activeren** Kies actief thema (wordt opgeslagen in `config.json`)
3. **SCSS compileren** - Verwerk SCSS naar CSS 3. **SCSS compileren** Verwerk SCSS naar CSS (geforceerd)
4. **Nieuw thema** - Eigen thema aanmaken 4. **Nieuw thema** Eigen thema aanmaken via admin of handmatig
## Thema structuur ## Thema structuur
``` ```
themes/default/ themes/default/
├── theme.json # Thema configuratie ├── theme.json # { title, config.default_template, template: layout→.twig }
├── base.twig # Hoofd layout ├── base.twig # Hoofd layout (head, header, nav, breadcrumb, footer)
├── full_content.twig # Layouts ├── full_content.twig # Layout: volledige breedte
├── partials/ # Header, nav, footer ├── left_sidebar.twig # Layout: sidebar links
── assets/ # CSS, JS, afbeeldingen ── right_sidebar.twig # Layout: sidebar rechts
``` ├── custom1.twig # Layout: custom
├── guide.twig # Layout: handleiding met sidebar (Navigation plugin)
├── partials/ # header.twig, navigation.twig, footer.twig
└── assets/
├── scss/theme.scss # SCSS bron (enige CSS bron — handmatige css/theme.css mag niet bestaan)
├── css_compiled/ # Gegenereerd door scssphp (read-only, niet handmatig aanpassen)
├── css/ # Externe CSS (bootstrap.min.css, bootstrap-icons.css, mobile.css)
├── js/ # app.js, bootstrap.bundle.min.js
├── fonts/ # bootstrap-icons.woff, woff2
└── img/ # favicon, icon, world-map
```
## theme.json
```json
{
"title": "default",
"config": {
"default_template": "full_content"
},
"template": {
"full_content": "full_content.twig",
"left_sidebar": "left_sidebar.twig",
"right_sidebar": "right_sidebar.twig",
"custom1": "custom1.twig",
"guide": "guide.twig"
}
}
```
- `title` — Weergavenaam in admin
- `config.default_template` — Standaard layout voor pagina's zonder `layout:` frontmatter
- `template` — Mapping van layout naam naar `.twig` bestand
## SCSS compilatie
- `ThemeManager` compileert `assets/scss/theme.scss` runtime naar `assets/css_compiled/theme.css` via scssphp
- `css_compiled/` is **read-only** — niet handmatig aanpassen
- `assets/css/theme.css` mag **niet** bestaan; anders negeert `ThemeManager::getCssUrl()` de SCSS
- Na SCSS wijzigingen: verwijder `assets/css_compiled/theme.css` en `.mtime` om te forceren
## Layouts
Layouts worden gekozen via frontmatter `layout:` key in content bestanden. Onbekende layouts vallen terug op `config.default_template` uit `theme.json`.
## guide.twig
Speciale layout voor handleidingen. Injecteert de Navigation plugin in de sidebar voor zijbalk navigatie. Wordt automatisch gebruikt voor pagina's in de `guide/` map.
+15 -8
View File
@@ -2,13 +2,20 @@
De CodePress developer handleiding bevat de volgende onderwerpen: De CodePress developer handleiding bevat de volgende onderwerpen:
- **Architectuur** - CMS architectuur en mappenstructuur - **Architectuur** CMS architectuur en mappenstructuur
- **Core classes** - CodePressCMS, ThemeManager, PluginManager - **Core classes** CodePressCMS, ThemeManager, PluginManager, AdminAuth
- **Plugin development** - Plugins ontwikkelen - **Plugin development** Plugin types (content/systeem), structuur, API
- **Routing** - Frontend en admin routing - **Routing** Frontend, admin en plugin admin routing
- **Beveiliging** - XSS, CSRF, path traversal - **Beveiliging** XSS, CSRF, path traversal, RBAC
- **Testing** - Penetratie, accessibility en functionele tests - **Testing** Penetratie, accessibility en functionele tests
- **Debugging** - Logging en cache - **Debugging** Logging en cache
- **Performance** - OPcache en SCSS caching - **Performance** OPcache en SCSS caching
Belangrijke concepten in CodePress 2.5.2:
- **Plugin types** — Content plugins (sidebar) en systeem plugins (admin menu, routes, API)
- **Admin plugin API** — Systeem plugins kunnen admin menu items en routes registreren
- **SCSS compilatie** — `ThemeManager` compileert SCSS naar `css_compiled/` via scssphp (read-only)
- **Asset serving** — `public/asset.php` serveert themes/, admin/assets/ en plugins/ op Apache (i.p.v. PHP dev router)
Selecteer een onderwerp uit de navigatie aan de linkerkant. Selecteer een onderwerp uit de navigatie aan de linkerkant.
+80 -7
View File
@@ -1,11 +1,84 @@
# CMS Architectuur # CMS Architectuur
CodePress is een file-based CMS zonder database. Content, configuratie en gebruikers worden opgeslagen in bestanden.
## Mappenstructuur
``` ```
codepress/ codepress/
├── cms/core/ # Core engine ├── cms/ # Core CMS engine
├── admin/ # Admin console │ ├── core/
├── themes/ # Thema's │ │ ├── class/
├── plugins/ # Plugins │ │ │ ├── CodePressCMS.php # Hoofd CMS class (routing, rendering, breadcrumb)
├── content/ # Content │ │ │ ├── ThemeManager.php # Thema-resolver + Twig render + SCSS compile
└── public/ # Web root │ │ │ ├── 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); $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 ## ThemeManager.php
Themabeheer in `cms/core/class/ThemeManager.php`: Themabeheer in `cms/core/class/ThemeManager.php`:
@@ -19,14 +26,84 @@ $themeManager = new ThemeManager($config);
$themeManager->getActiveTheme(); $themeManager->getActiveTheme();
$themeManager->renderTwig($template, $data); $themeManager->renderTwig($template, $data);
$themeManager->compileCss($force); $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 ## PluginManager.php
Plugin systeem in `cms/core/class/PluginManager.php`: Plugin systeem in `cms/core/plugin/PluginManager.php`:
```php ```php
$pluginManager = new PluginManager(); $pluginManager = new PluginManager($pluginsPath, $enabledPlugins);
$pluginManager->loadPlugins($enabledPlugins); $pluginManager->getSidebarContent($allowedPlugins);
$pluginManager->getPluginCssUrls();
$pluginManager->executeHook($name, $params); $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 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 ## Plugin structuur
``` ```
plugins/MijnPlugin/ plugins/MijnPlugin/
├── plugin.json # Plugin metadata ├── MijnPlugin.php # Plugin code (NIET plugin.php)
├── plugin.php # Plugin code ├── plugin.json # Metadata met type veld
── config.json # Optionele configuratie ── 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 ## plugin.json
```json ```json
{ {
"name": "Mijn Plugin", "name": "Mijn Plugin",
"version": "1.0.0", "version": "1.0.0",
"author": "Jouw Naam", "author": "Jouw Naam",
"description": "Beschrijving" "description": "Beschrijving",
"type": "content"
} }
``` ```
## plugin.php voorbeeld - `name` — Weergavenaam
- `type``"content"` of `"system"` (default: `content`)
## Content plugin voorbeeld
```php ```php
<?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 ## CMSAPI gebruiken
```php ```php
<?php <?php
require_once '../../cms/core/class/PluginManager.php';
$api = PluginManager::getAPI(); $api = PluginManager::getAPI();
$config = $api->getConfig(); $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 ## 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 ### PHP dev server
// Schone URLs: /nl/pagina
// Query: ?page=pagina&lang=nl 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 ## 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 ```php
// Routes: /admin/dashboard, /admin/content, etc. // PluginManager roept deze aan voor /admin/mijn-systeem
// Query parameter: ?route=dashboard $plugin->handleAdminRoute('mijn-systeem');
``` ```
@@ -4,28 +4,48 @@ Content wordt opgeslagen in de `content/` map zonder database.
## Ondersteunde bestandsformaten ## Ondersteunde bestandsformaten
- `.md` - Markdown (aanbevolen) - `.md` Markdown (aanbevolen)
- `.php` - Dynamische PHP pagina's - `.php` Dynamische PHP pagina's
- `.html` - Statische HTML pagina's - `.html` Statische HTML pagina's
## Bestandsnaam conventies ## Bestandsnaam conventies
``` ```
nl.pagina-naam.md # Nederlandse pagina nl.pagina-naam.md # Nederlandse pagina
en.page-name.md # Engelse pagina en.page-name.md # Engelse pagina
nl.map/ # Nederlandse map (vereist index bestand om klikbaar te zijn)
``` ```
Taalprefix wordt dynamisch verwijderd op basis van beschikbare talen via `getAvailableLanguages()`.
## Frontmatter ## Frontmatter
Markdown bestanden kunnen frontmatter metadata bevatten: Markdown bestanden kunnen frontmatter metadata bevatten:
```markdown ```markdown
--- ---
layout: full_content layout: left_sidebar
plugins: HTMLBlock plugins:
- HTMLBlock
- Navigation
--- ---
# Pagina titel # Pagina titel
Content... Content...
``` ```
## Frontmatter velden
- `layout` — Layout naam (moet voorkomen in `theme.json` template mapping; fallback op `config.default_template`)
- `plugins` — Lijst van content plugins die in de sidebar verschijnen
### plugins veld
Het `plugins` veld bepaalt:
- **Welke plugins** in de sidebar verschijnen (alleen content plugins, niet systeem plugins)
- **De volgorde** van de plugins in de sidebar (top tot onder)
De volgorde in de frontmatter is de volgorde waarin de plugins worden getoond. In de admin content-edit pagina kun je de volgorde aanpassen met up/down knoppen; de frontmatter wordt live bijgewerkt.
Plugins worden niet getoond als de gekozen layout geen sidebar heeft (bijv. `full_content`).
+36 -4
View File
@@ -5,12 +5,44 @@
1. Login op `/admin` 1. Login op `/admin`
2. Ga naar **Content** 2. Ga naar **Content**
3. Kies een map of maak een nieuwe pagina 3. Kies een map of maak een nieuwe pagina
4. Bewerk content in de editor 4. Bewerk content in de CodeMirror editor
5. Sla op met Ctrl+S 5. Sla op met Ctrl+S
## Editor functies ## Editor functies
- **CodeMirror** editor met syntax highlighting - **CodeMirror** editor met syntax highlighting (Markdown, PHP, HTML)
- **Toolbar** voor snel Markdown invoegen - **Toolbar** voor snel Markdown invoegen
- **Live preview** via knop - **Sneltoetsen**: Ctrl+S (opslaan), Ctrl+N (nieuw)
- **Auto-save** backups in `.bak/` map - **Auto-save** backups in `.bak/` map
## Layout selectie
Op de content-edit pagina kun je de layout kiezen uit de layouts gedefinieerd in `theme.json` (template mapping). De geselecteerde layout wordt opgeslagen in de frontmatter `layout:` key.
```markdown
---
layout: left_sidebar
---
```
Onbekende layouts vallen terug op `config.default_template` uit `theme.json`.
## Plugin selectie en volgorde
Op de content-edit pagina kun je content plugins kiezen voor de sidebar:
- **Selectie** — Alleen content plugins (uit `plugin.json` met `type: "content"`) verschijnen in de plugin selectie
- **Volgorde** — Pas de volgorde aan met up/down knoppen
- **Frontmatter update** — De frontmatter `plugins:` key wordt live bijgewerkt bij wijzigingen
- **Layout zonder sidebar** — Plugins worden verborgen als de gekozen layout geen sidebar heeft (bijv. `full_content`)
```markdown
---
layout: left_sidebar
plugins:
- HTMLBlock
- Navigation
---
```
De volgorde in de frontmatter bepaalt de volgorde van de plugins in de sidebar (top tot onder).
+9
View File
@@ -1,3 +1,12 @@
# Handleiding # Handleiding
Welkom bij de CodePress CMS handleiding (versie 2.5.2). CodePress is een file-based CMS zonder database — content, configuratie en gebruikers worden opgeslagen in bestanden.
De handleiding is verdeeld in vier secties:
- **Admin Beheerder** — Beheer van de website: dashboard, content, configuratie, thema's, beveiliging, plugins (content en systeem), gebruikers met rollen, statistieken en logs
- **Content Beheerder** — Content beheren: structuur, pagina's beheren (layout selectie, plugin volgorde), media en de Content API
- **Theme Developer** — Thema's ontwikkelen: structuur, `theme.json`, Twig templates, SCSS styling (enige CSS bron), layouts en nieuwe thema's
- **CodePress Developer** — Core ontwikkeling: architectuur, core classes, plugin development (content/systeem), routing, beveiliging (RBAC), testing, debugging en performance
Selecteer een onderwerp uit de navigatie aan de linkerkant. Selecteer een onderwerp uit de navigatie aan de linkerkant.
+54 -8
View File
@@ -1,5 +1,7 @@
# Layouts # Layouts
Layouts definiëren de pagina structuur (sidebar links, volledige breedte, etc.). Layouts worden gedefinieerd in `theme.json` en gekozen via frontmatter in content bestanden.
## Layout kiezen in content ## Layout kiezen in content
```markdown ```markdown
@@ -14,14 +16,58 @@ Content...
## Layouts in theme.json ## Layouts in theme.json
Layouts worden gedefinieerd in de `template` mapping. De `config.default_template` is de fallback voor pagina's zonder `layout:` frontmatter of met een onbekende layout:
```json ```json
{ {
"default_layout": "full_content", "config": {
"layouts": { "default_template": "full_content"
"full_content": "full_content.twig", },
"left_sidebar": "left_sidebar.twig", "template": {
"right_sidebar": "right_sidebar.twig", "full_content": "full_content.twig",
"custom1": "custom1.twig" "left_sidebar": "left_sidebar.twig",
} "right_sidebar": "right_sidebar.twig",
"custom1": "custom1.twig",
"guide": "guide.twig"
}
} }
``` ```
## Layout template
Een layout template extends `base.twig` en vult het `content` block:
```twig
{% extends 'base.twig' %}
{% block content %}
<div class="container">
{{ content|raw }}
</div>
{% endblock %}
```
## Layouts met sidebar
Layouts met sidebar kunnen plugin content tonen:
```twig
{% extends 'base.twig' %}
{% block content %}
<div class="row">
<main class="col-md-8">
{{ content|raw }}
</main>
<aside class="col-md-4">
{{ sidebar_content|raw }}
</aside>
</div>
{% endblock %}
```
Als een pagina geen plugins heeft of de layout geen sidebar bevat, is `sidebar_content` leeg.
## Guide layout
De `guide` layout (`guide.twig`) is speciaal voor handleidingen. Het injecteert de Navigation plugin in de sidebar voor zijbalk navigatie. Wordt automatisch gebruikt voor pagina's in de `guide/` map.
+38 -9
View File
@@ -2,20 +2,49 @@
``` ```
themes/mijn-thema/ themes/mijn-thema/
├── theme.json # Thema configuratie ├── theme.json # { title, config.default_template, template: layout→.twig }
├── base.twig # Hoofd layout ├── base.twig # Hoofd layout (head, header, nav, breadcrumb, footer)
├── full_content.twig # Layout: full-width ├── full_content.twig # Layout: volledige breedte
├── left_sidebar.twig # Layout: sidebar links ├── left_sidebar.twig # Layout: sidebar links
├── right_sidebar.twig # Layout: sidebar rechts ├── right_sidebar.twig # Layout: sidebar rechts
├── custom.twig # Layout: custom ├── custom1.twig # Layout: custom
├── guide.twig # Layout: handleiding met sidebar (Navigation plugin)
├── partials/ ├── partials/
│ ├── header.twig │ ├── header.twig
│ ├── navigation.twig │ ├── navigation.twig
│ └── footer.twig │ └── footer.twig
└── assets/ └── assets/
├── scss/theme.scss # SCSS bron ├── scss/theme.scss # SCSS bron (de enige CSS bron)
├── css/ # CSS bestanden ├── css_compiled/ # Gegenereerd door scssphp (read-only, niet handmatig aanpassen)
├── js/theme.js # JavaScript ├── css/ # Externe CSS (bootstrap.min.css, bootstrap-icons.css, mobile.css)
├── fonts/ # Lettertypes ├── js/ # app.js, bootstrap.bundle.min.js
── img/ # Afbeeldingen ── fonts/ # bootstrap-icons.woff, woff2
└── img/ # favicon, icon, world-map
```
## SCSS is de enige CSS bron
- **ALTIJD** `assets/scss/theme.scss` aanpassen — dit is de enige CSS bron
- `ThemeManager` compileert SCSS runtime naar `assets/css_compiled/theme.css` via scssphp
- `assets/css_compiled/` is **read-only** — niet handmatig aanpassen
- **NOOIT** `assets/css/theme.css` handmatig aanmaken of aanpassen; dit bestand mag niet bestaan
- `ThemeManager::getCssUrl()` prioriteit: 1) `assets/css/theme.css` (handmatig), 2) `assets/css_compiled/theme.css` (gecompileerd). Als `theme.css` bestaat, wordt de SCSS negeren.
- Na SCSS wijzigingen: verwijder `assets/css_compiled/theme.css` en `.mtime` om te forceren
```bash
rm themes/mijn-thema/assets/css_compiled/theme.css themes/mijn-thema/assets/css_compiled/.mtime
```
## guide.twig
Speciale layout voor handleidingen. Injecteert de Navigation plugin in de sidebar voor zijbalk navigatie. Wordt automatisch gebruikt voor pagina's in de `guide/` map.
## Plugin CSS laden
Plugin CSS wordt automatisch geladen ná theme CSS in `base.twig`, zodat thema's plugin styling kunnen overschrijven:
```twig
{% for cssUrl in plugin_css_urls|default([]) %}
<link href="{{ cssUrl }}" rel="stylesheet">
{% endfor %}
``` ```
+37 -12
View File
@@ -2,20 +2,45 @@
```json ```json
{ {
"title": "Mijn Thema", "title": "Mijn Thema",
"default_layout": "full_content", "config": {
"header_color": "#0a369d", "default_template": "full_content"
"layouts": { },
"full_content": "full_content.twig", "template": {
"left_sidebar": "left_sidebar.twig", "full_content": "full_content.twig",
"right_sidebar": "right_sidebar.twig" "left_sidebar": "left_sidebar.twig",
} "right_sidebar": "right_sidebar.twig",
"custom1": "custom1.twig",
"guide": "guide.twig"
}
} }
``` ```
## Velden ## Velden
- `title` - Weergavenaam in admin - `title` Weergavenaam in admin
- `default_layout` - Standaard layout voor nieuwe pagina's - `config.default_template` Standaard layout voor pagina's zonder `layout:` frontmatter (fallback bij onbekende layouts)
- `header_color` - Kleur admin sidebar - `template` — Mapping van layout naam naar `.twig` bestand
- `layouts` - Mapping van layout namen naar .twig bestanden
## Template mapping
De `template` mapping definieert welke layouts beschikbaar zijn. Elke key is een layout naam, elke value is het `.twig` bestand:
| Layout naam | Twig bestand | Beschrijving |
|-------------|--------------|--------------|
| `full_content` | `full_content.twig` | Volledige breedte, geen sidebar |
| `left_sidebar` | `left_sidebar.twig` | Sidebar links |
| `right_sidebar` | `right_sidebar.twig` | Sidebar rechts |
| `custom1` | `custom1.twig` | Custom layout |
| `guide` | `guide.twig` | Handleiding met sidebar (Navigation plugin) |
## Layout keuze
- Layouts worden gekozen via frontmatter `layout:` key in content bestanden
- Onbekende layouts vallen terug op `config.default_template`
- `ThemeManager::getTemplates()` geeft de template mapping terug
- `ThemeManager::getConfig()` geeft de config sectie terug (inclusief `default_template`)
## Guide layout
De `guide` layout is speciaal voor handleidingen. `getGuidePage()` in `CodePressCMS.php` injecteert automatisch de Navigation plugin in de metadata voor zijbalk navigatie.