228 lines
16 KiB
Markdown
228 lines
16 KiB
Markdown
# Agent Instructions for CodePress CMS
|
|
|
|
## AI Model
|
|
- **Huidig model**: GLM-5.2 max (Ollama cloud)
|
|
- Sessie gestart: 16 feb 2026
|
|
|
|
## Build & Run
|
|
- **Run Server**: `php -S localhost:8080 cms/router.php` (router nodig voor clean URLs)
|
|
- **Lint PHP**: `find . -name "*.php" -not -path "./vendor/*" -not -path "./var/*" -exec php -l {} \;`
|
|
- **Dependencies**: Composer vereist voor CommonMark, Twig en scssphp. Geen NPM.
|
|
- **Admin Console**: Toegankelijk op `/admin` (standaard login: `admin` / `admin`)
|
|
|
|
## Project Structuur
|
|
```
|
|
codepress/
|
|
├── cms/ # Core CMS engine
|
|
│ ├── core/
|
|
│ │ ├── class/
|
|
│ │ │ ├── CodePressCMS.php # Hoofd CMS class (routing, rendering, breadcrumb, guide)
|
|
│ │ │ ├── ThemeManager.php # Thema-resolver + Twig render + SCSS compile
|
|
│ │ │ ├── ContentAPI.php # Read-only API voor PHP content bestanden
|
|
│ │ │ ├── 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 systeem (SQLite/syslog)
|
|
│ │ │ ├── RateLimiter.php # Rate limiting per IP
|
|
│ │ │ ├── RequestLogger.php # Request logging + visitor info
|
|
│ │ │ ├── SearchEngine.php # Volledige tekst zoekfunctie
|
|
│ │ │ ├── SimpleTemplate.php # Legacy Mustache-style engine (niet meer gebruikt)
|
|
│ │ │ └── AccessibilityManager.php # Accessibility features
|
|
│ │ ├── plugin/
|
|
│ │ │ ├── PluginManager.php # Plugin loader (laadt, hooks, filters, sidebar)
|
|
│ │ │ └── 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 (serveert themes/, admin/assets/, plugins/assets/)
|
|
├── themes/ # Dynamische thema's (volledig zelfstandig)
|
|
│ ├── default/ # Standaard thema
|
|
│ │ ├── theme.json # { title, config.default_template, template: layout→.twig mapping }
|
|
│ │ ├── base.twig # Hoofd layout (head, header, nav, breadcrumb, footer)
|
|
│ │ ├── full_content.twig # Layout: volledige breedte
|
|
│ │ ├── left_sidebar.twig # Layout: sidebar links
|
|
│ │ ├── 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 (runtime gecompileerd)
|
|
│ │ ├── css/theme.css # Gecompileerde CSS
|
|
│ │ ├── css/style.css # Extra CSS (search fix, etc.)
|
|
│ │ ├── css/bootstrap.min.css # Bootstrap 5
|
|
│ │ ├── css/bootstrap-icons.css # Bootstrap Icons
|
|
│ │ ├── css/mobile.css # Mobile styles
|
|
│ │ ├── js/app.js # Thema JavaScript
|
|
│ │ ├── js/bootstrap.bundle.min.js
|
|
│ │ ├── fonts/ # bootstrap-icons.woff, woff2
|
|
│ │ └── img/ # favicon, icon, world-map
|
|
│ └── demo/ # Demo thema (zelfde structuur, andere look)
|
|
├── admin/ # Admin paneel
|
|
│ ├── config/
|
|
│ │ ├── app.php # Admin app configuratie (paths, config_json, etc.)
|
|
│ │ └── admin.json # Gebruikers & security (file-based, .gitignore'd)
|
|
│ ├── src/
|
|
│ │ └── AdminAuth.php # Authenticatie (sessies, bcrypt, CSRF, lockout, RBAC)
|
|
│ ├── theme/default/ # Admin thema
|
|
│ │ ├── theme.json # Admin thema configuratie
|
|
│ │ ├── assets/
|
|
│ │ │ ├── css/
|
|
│ │ │ │ ├── style.css # Admin styles (code blocks, guide nav)
|
|
│ │ │ │ ├── editor.css # CodeMirror editor styles
|
|
│ │ │ │ ├── bootstrap.min.css
|
|
│ │ │ │ └── bootstrap-icons.css
|
|
│ │ │ ├── js/
|
|
│ │ │ │ ├── app.js
|
|
│ │ │ │ ├── editor-toolbar.js # CodeMirror toolbar + shortcuts
|
|
│ │ │ │ ├── keyboard-navigation.js
|
|
│ │ │ │ └── bootstrap.bundle.min.js
|
|
│ │ │ ├── codemirror/ # CodeMirror editor (modes, addons)
|
|
│ │ │ ├── fonts/ # bootstrap-icons.woff, woff2
|
|
│ │ │ └── img/ # favicon, world-map
|
|
│ │ └── views/
|
|
│ │ ├── login.twig # Login pagina
|
|
│ │ ├── layouts/
|
|
│ │ │ └── admin.twig # Admin layout met sidebar (role-based zichtbaarheid)
|
|
│ │ └── pages/
|
|
│ │ ├── dashboard.twig # Dashboard (role-based inhoud)
|
|
│ │ ├── content.twig # Content beheer
|
|
│ │ ├── content-edit.twig # Content bewerken (layout select, plugins, CodeMirror)
|
|
│ │ ├── content-new.twig # Nieuwe content
|
|
│ │ ├── content-move-form.twig # Content verplaatsen
|
|
│ │ ├── content-dir-form.twig # Map hernoemen
|
|
│ │ ├── config.twig # Site configuratie
|
|
│ │ ├── security.twig # Beveiliging instellingen
|
|
│ │ ├── theme.twig # Thema beheer
|
|
│ │ ├── theme-new.twig # Nieuw thema
|
|
│ │ ├── plugins.twig # Plugin beheer (beschermd: essentiële plugins)
|
|
│ │ ├── plugins-edit.twig # Plugin bewerken (CodeMirror)
|
|
│ │ ├── plugins-new.twig # Nieuwe plugin
|
|
│ │ ├── plugin-config.twig # Plugin configuratie
|
|
│ │ ├── users.twig # Gebruikersbeheer (rollen, wachtwoord)
|
|
│ │ ├── statistics.twig # Statistieken
|
|
│ │ ├── logs.twig # Log viewer
|
|
│ │ ├── media.twig # Media beheer
|
|
│ │ ├── guide.twig # Handleiding (met Navigation sidebar)
|
|
│ │ ├── update.twig # Update pagina
|
|
│ │ └── error.twig # 403/404 fout pagina
|
|
│ └── storage/ # Logs, cache, geoip
|
|
├── plugins/ # CMS plugins
|
|
│ ├── Navigation/ # Essentiële navigatie plugin (beschermd)
|
|
│ │ ├── Navigation.php # Plugin code (guide + content navigatie)
|
|
│ │ ├── plugin.json # Plugin metadata
|
|
│ │ ├── assets/
|
|
│ │ │ ├── scss/navigation.scss # SCSS bron
|
|
│ │ │ └── css/navigation.css # Gecompileerde CSS
|
|
│ │ └── views/ # Plugin Twig templates (toekomstig)
|
|
│ └── HTMLBlock/ # Voorbeeld sidebar plugin
|
|
│ └── HTMLBlock.php
|
|
├── content/ # Website content (.md, .php, .html)
|
|
├── public/ # Web root
|
|
│ ├── index.php # Website entry point
|
|
│ ├── admin.php # Admin entry point + routing
|
|
│ ├── favicon.ico
|
|
│ └── robots.txt
|
|
├── guide/ # Handleidingen (nl/en, gesplitst in mappen)
|
|
│ ├── nl/ # Nederlandse handleidingen
|
|
│ │ ├── index.md # Index (verwijst naar onderwerpen)
|
|
│ │ ├── admin-beheerder.md # Admin handleiding (inleiding)
|
|
│ │ ├── admin-beheerder/ # Sub-onderdelen
|
|
│ │ ├── content-beheerder.md
|
|
│ │ ├── content-beheerder/
|
|
│ │ ├── codepress-developer.md
|
|
│ │ ├── codepress-developer/
|
|
│ │ ├── theme-developer.md
|
|
│ │ └── theme-developer/
|
|
│ ├── en/ # Engelse handleidingen (zelfde structuur als nl/)
|
|
│ └── README.md
|
|
├── cli/ # CLI scripts & tests
|
|
│ └── test/
|
|
│ ├── accessibility.sh # WCAG 2.1 AA test suite
|
|
│ ├── enhanced-suite.sh # Enhanced test suite
|
|
│ ├── functional/ # Functionele testen
|
|
│ └── pentest/ # Penetratietesten
|
|
├── var/ # Cache (twig) — .gitignore'd
|
|
├── config.json # Site configuratie — .gitignore'd
|
|
├── composer.json # PHP dependencies
|
|
├── version.php # Versie informatie (huidige: 2.5.1)
|
|
├── .gitignore # Negeert: var/, config.json, admin/config/admin.json, content/
|
|
└── AGENTS.md # Dit bestand
|
|
```
|
|
|
|
## Code Style & Conventions
|
|
- **PHP Standards**: Follow PSR-12. Use 4 spaces for indentation.
|
|
- **Naming**: Classes `PascalCase` (e.g., `CodePressCMS`), methods `camelCase` (e.g., `renderMenu`), variables `camelCase`, config keys `snake_case`.
|
|
- **Architecture**:
|
|
- Core CMS logic in `cms/core/class/CodePressCMS.php`
|
|
- Bootstrap/requires in `cms/core/index.php`
|
|
- Configuration loaded from `config.json` via `cms/core/config.php`
|
|
- Public website entry point: `public/index.php`
|
|
- Admin entry point + routing: `public/admin.php`
|
|
- Admin authentication + RBAC: `admin/src/AdminAuth.php`
|
|
- Admin theme: `admin/theme/default/` (views + assets)
|
|
- Plugin assets: `plugins/<Name>/assets/` (served via router `/plugins/<Name>/assets/`)
|
|
- **Content**: Stored in `content/`. Supports `.md` (Markdown), `.php` (Dynamic), `.html` (Static).
|
|
- **Templating**: Twig templates in `themes/<naam>/`. `ThemeManager` rendert via Twig en compileert `assets/scss/theme.scss` runtime naar `assets/css/theme.css`. Layout gekozen via frontmatter `layout:` key; onbekende layouts vallen terug op `config.default_template` in `theme.json`.
|
|
- **Plugin CSS**: Plugins hebben eigen `assets/scss/` en `assets/css/`. Plugin CSS wordt automatisch geladen na 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/...`.
|
|
- **Navigation**: Auto-generated from directory structure. Folders require an index file to be clickable in breadcrumbs. Breadcrumb is dynamisch: Home > [submappen] > [pagina]. Homepage toont altijd het pad.
|
|
- **Security**:
|
|
- Always use `htmlspecialchars()` for outputting user/content data
|
|
- Use `realpath()` + prefix-check for path traversal prevention
|
|
- Admin forms require CSRF tokens via `AdminAuth::verifyCsrf()`
|
|
- Passwords stored as bcrypt hashes in `admin/config/admin.json`
|
|
- Role-based access control (RBAC) via `AdminAuth::hasPermission()`
|
|
- **Git**: `main` is the clean CMS core. `development` is de actieve development branch. `e.noorlander` bevat persoonlijke content. Niet mixen.
|
|
|
|
## Admin Console
|
|
- **File-based**: Geen database. Gebruikers opgeslagen in `admin/config/admin.json`
|
|
- **Routing**: Via clean URLs `/admin/<route>` (omgezet naar `?route=` door `cms/router.php`)
|
|
- **Routes**: `login`, `logout`, `dashboard`, `content`, `content-edit`, `content-new`, `content-delete`, `content-dir-create`, `content-dir-rename`, `content-dir-delete`, `content-move`, `config`, `security`, `theme`, `theme-new`, `plugins`, `plugins-new`, `plugins-edit`, `plugins-config`, `plugins-toggle`, `plugins-delete`, `users`, `statistics`, `logs`, `media`, `guide`, `update`
|
|
- **Auth**: Session-based. `AdminAuth` class handelt login, logout, CSRF, brute-force lockout af
|
|
- **Templates**: Twig templates in `admin/theme/default/views/pages/`. Layout in `admin/theme/default/views/layouts/admin.twig`
|
|
- **Essentiële plugins**: Gedefinieerd in `getProtectedPlugins()` in `public/admin.php`. Deze plugins kunnen niet worden gedeactiveerd, bewerkt of verwijderd. Huidige essentiële plugins: `Navigation`.
|
|
|
|
## Gebruikersrollen (RBAC)
|
|
Gedefinieerd in `AdminAuth::ROLE_PERMISSIONS` als een mapping van rol → toegestane routes.
|
|
|
|
| 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 |
|
|
|
|
- Sidebar items worden conditioneel getoond via `has_permission()` Twig function
|
|
- Dashboard inhoud is role-based (statistieken, content stats, systeem info, quick actions)
|
|
- Route access control in `public/admin.php`: onbevoegde routes geven 403 error
|
|
|
|
## Guide Systeem
|
|
- Handleidingen in `guide/<lang>/` met sub-onderdelen in aparte mappen
|
|
- NL en EN hebben identieke structuur (bestandsnamen zijn gelijk voor fallback)
|
|
- `getGuidePage()` in `CodePressCMS.php` laadt guide content en injecteert `plugins: Navigation` in metadata
|
|
- Navigation plugin genereert zijbalk navigatie vanuit de mapstructuur (guide + content)
|
|
- Guide titles worden uit H1 van markdown bestanden gehaald (via `getTitleFromFile()`)
|
|
- Admin guide laadt Navigation plugin direct in `handleGuide()` in `public/admin.php`
|
|
|
|
## Important: Title vs File/Directory Name Logic
|
|
- **CRITICAL**: When user asks for "title" corrections, they usually mean **FILE/DIRECTORY NAME WITHOUT LANGUAGE PREFIX AND EXTENSIONS**, not the HTML title from content!
|
|
- **Examples**:
|
|
- `nl.test.md` → display as "Test" (not content title)
|
|
- `nl.test/` directory → display as "Test" (not H1 content)
|
|
- `en.php-testen` → display as "Php Testen" (not "ICT")
|
|
- **Method**: Use `formatDisplayName()` to process file/directory names correctly
|
|
- **Priority**: Directory names take precedence over file names when both exist
|
|
- **Language prefixes**: Dynamisch verwijderd op basis van beschikbare talen via `getAvailableLanguages()`
|
|
|
|
## Bekende aandachtspunten
|
|
- LSP errors over "Undefined function" in PHP files zijn vals-positief (standaard PHP functies worden niet herkend door de LSP). Negeer deze.
|
|
- Zie `TODO.md` voor alle openstaande verbeteringen en nieuwe features.
|
|
- `vendor/` map bevat Composer dependencies (CommonMark, Twig, scssphp). Niet handmatig wijzigen.
|
|
- `admin/config/admin.json` bevat wachtwoord-hashes. Niet committen met echte productie-wachtwoorden.
|
|
- `config.json` staat in `.gitignore`. Niet committen.
|
|
- `var/` (Twig cache) staat in `.gitignore`. Kan veilig worden gewist: `rm -rf var/cache/twig/*`
|
|
- `content/` staat in `.gitignore`. Content wordt lokaal beheerd.
|
|
- Pad-referenties vanuit `public/admin.php`: gebruik `__DIR__ . "/../themes/..."` (één niveau omhoog), NIET `../../` (twee niveaus).
|