# CodePress CMS v2.6.2 — Release Notes **Release datum:** 2026-08-19 **Codename:** Lyra **Status:** stable --- ## Samenvatting Deze release brengt de **thema-editor** en de **content-editor** op hetzelfde niveau als de plugin-editor. Thema's en content zijn nu volledig bewerkbaar in de admin met een bestandsbrowser zijbalk, uploaden/verwijderen/verplaatsen, en SCSS-compile (thema's) of git/backup-integratie (content). Daarnaast is de bestandsscanner geünificeerd tot één herbruikbare `scanEditorFiles()` functie. Beide grote features zijn geïmplementeerd als spiegel van de plugin-editor (`/admin/plugins-edit`), zodat de editor-ervaring consistent is voor plugins, thema's en content. --- ## Nieuwe features ### 1. Thema editor (thema's net zo bewerkbaar maken als plugins) De thema-beheer pagina toonde alleen thema-kaarten met activeren/compileer knoppen. Nu is elk thema volledig bewerkbaar via `/admin/theme-edit`. #### Bestandsbrowser zijbalk - Geneste, inklapbare boomstructuur van alle bestanden in de thema-map (`.twig`, `.json`, `.scss`, `.css`, `.js`, `.html`, `.md`, `.php`) inclusief `partials/` en `assets/` submappen - `assets/css_compiled/` (runtime artefact, read-only) wordt verborgen in de boom - `scanThemeFiles()` helper — recursieve boom-opbouw met path-traversal bescherming; skipt `css_compiled/` - Mappen die het actieve bestand bevatten worden automatisch uitgeklapt - Iconen per bestandstype (TWIG, PHP, JSON, MD, CSS, JS, HTML, mappen) #### Nieuw bestand aanmaken - "Nieuw bestand" knop + modal met pad-invoer (bijv. `partials/header.twig` of `assets/scss/_variables.scss`) - Submappen worden automatisch aangemaakt - Stub-content per extensie (`{% extends 'base.twig' %}` voor TWIG, `{\n}\n` voor JSON, enz.) - Path-traversal bescherming: `../`/`..\\`/`./` stripping + `..`/`.` segment-guard + realpath prefix-check #### Uploaden / Verwijderen / Verplaatsen - Upload-knop + inklapbaar upload-formulier dat bestanden opslaat in `themes//assets/` - Toegestane extensies: afbeeldingen, video, audio, PDF, ZIP, CSS, SCSS, JS, JSON, HTML, MD, TWIG, fonts - Per-bestand prullenbak-icoon en verplaats-icoon in de bestandsboom - `theme.json` is beschermd: kan bewerkt maar niet verwijderd of verplaatst worden #### SCSS compileren vanuit de editor - "SCSS compileren" knop bovenaan de editor (alleen als `assets/scss/theme.scss` bestaat) - Toont compile-status: **up-to-date** (groen) of **verouderd** (geel) - Forceert compilatie via `ThemeManager::compileCss(true)` #### Thema overzicht + activeren + verwijderen - `theme.twig` vernieuwd: bewerken/activeer/verwijder/compileer knoppen per thema-kaart - SCSS-status badges per thema (up-to-date / verouderd) - **Activeren**: zet `active_theme` in `config.json` (nieuwe route `theme-activate`) - **Verwijderen**: alleen niet-actieve, niet-default thema's (nieuwe route `theme-delete`); default thema beschermd - **Nieuw thema met basis-kopie**: kies een bestaand thema als basis bij aanmaken; `css_compiled/` wordt niet gekopieerd; de `title` in `theme.json` wordt overschreven met de nieuwe themanaam; `README.md` krijgt een nieuwe header #### Uniforme thema-structuur Nieuwe thema's die via de admin worden aangemaakt krijgen automatisch een uniforme structuur: - `theme.json`, `base.twig`, `full_content.twig`, `partials/header.twig`, `partials/footer.twig` - `assets/scss/theme.scss` (starter SCSS), `assets/css/`, `assets/js/`, `assets/img/`, `assets/fonts/` - `README.md` per thema #### Media invoegen in editor - De media-modal ondersteunt nu ook thema-context: `/admin/media-list?theme=` scant `themes//assets/` - `_media-modal.twig` JS uitgebreid met `mediaThemeName` scope ### 2. Content editor (content consistent met plugins en thema's) De content-beheer pagina (`/admin/content`) was een klassieke tabelweergave. Nu is er een额外的 content-editor `/admin/content-files` met dezelfde bestandsbrowser-zijbalk-ervaring als de plugin- en thema-editors. Beide weergaven werken naast elkaar en gebruiken dezelfde content-map. #### Bestandsbrowser zijbalk - Geneste, inklapbare boomstructuur van alle bestanden in `content/` - `scanContentFiles()` helper — recursieve boom-opbouw met path-traversal bescherming; skipt `.bak/`, `.git/`, dotfiles - Bewerkbare extensies: `.md`, `.php`, `.html` (consistent met bestaande `content-edit`) - Per-map actie-knoppen: nieuw bestand, nieuwe map, hernoemen, verwijderen #### Nieuw bestand / map aanmaken - "Nieuw bestand" knop + modal met pad-invoer en extensie-keuze (Markdown/PHP/HTML) - `in_dir` prefix ondersteuning: bestand kan direct in een submap worden aangemaakt vanuit de zijbalk - Frontmatter met `layout`, `author_name`, `author_email`, `created` wordt automatisch gegenereerd - "Nieuwe map" knop + modal; submappen worden automatisch aangemaakt #### Uploaden / Verwijderen / Verplaatsen - Upload-knop + inklapbaar upload-formulier dat bestanden opslaat in `content/` (of een submap) - Toegestane extensies: afbeeldingen, video, audio, PDF, ZIP, office docs, CSS, SCSS, JS, JSON, HTML, MD - Per-bestand prullenbak-icoon en verplaats-icoon in de bestandsboom - Nieuwe routes: `content-file-upload`, `content-file-delete`, `content-file-move` #### Mappen beheer - **Nieuwe map** (`content-dir-create-in`): per map in de zijbalk of bovenaan - **Map hernoemen** (`content-dir-rename-in`): potlood-icoon per map - **Map verwijderen** (`content-dir-delete-in`): prullenbak-icoon per map (alleen lege mappen; verborgen `.bak` bestanden genegeerd) #### Layout selectie + plugins + frontmatter - Layout dropdown uit `theme.json` template mapping (zoals bestaande `content-edit`) - Plugin checkbox-groep voor `plugins:` frontmatter key - Author metadata, `created` datum in frontmatter - Live frontmatter-update bij layout/plugin wijziging (spiegel van `content-edit.twig` JS) #### Git / Backup integratie (Fase 5) Bovenaan de content-editor staan backup- en git-acties: - **Git init**: initialiseert een git repository in `content/` (als er nog geen is) - **Commit**: committed alle niet-committed wijzigingen (alleen als er een git repo is en er wijzigingen zijn) - **Backup**: link naar de backup-pagina (`/admin/content-backup`) voor ZIP backup/restore - Git status badge toont de huidige branch, of er niet-committed wijzigingen zijn (dirty/clean), en de laatste commit ### 3. Uniformiteit: één scanEditorFiles() voor alle editors De drie nagenoeg identieke scan-functies (`scanPluginFiles`, `scanThemeFiles`, `scanContentFiles`) zijn geünificeerd tot één herbruikbare functie: - `scanEditorFiles(string $dir, string $scope = 'plugin'): array` — hoofd-functie - `scanEditorFilesNode(string $absDir, string $relPath, string $realBase, array $skipPaths = []): array` — recursieve helper - Scope-specifieke skips via `$skipPaths` map (bijv. `['assets/css_compiled' => true]` voor themes) - `scanPluginFiles`/`scanThemeFiles`/`scanContentFiles` behouden als dunne wrappers voor backwards-compatibiliteit De file-upload/delete/move handler-families zijn per-scope behouden (plugin: protected-plugins check; theme: theme.json-bescherming; content: geen specifieke bescherming) — generalisatie zou een complexe configuratie-laag vereisen die de leesbaarheid niet verbetert. --- ## Bug fixes - **Thema-naam niet overgenomen bij kopiëren** — bij het aanmaken van een nieuw thema met een basisthema werd de `title` uit het basisthema's `theme.json` gekopieerd; nu wordt de `title` overschreven met de nieuwe themanaam en krijgt `README.md` een nieuwe header - **Mappen met `_` prefix zichtbaar in frontend navigatie** — mappen zoals `_drafts`, `_data` werden in het menu getoond omdat `scanDirectory()` alleen `.` en `-` prefixen oversloeg. Nu worden ook `_`-prefix mappen overgeslagen in `scanDirectory()`, `searchInDirectory()` en `scanForPageTitles()` (consistente filtering) - **Images in markdown niet weergegeven** — `![alt](test.svg)` werd gerenderd als `` (relatieve URL → 404) of `![alt](/content/test.svg)` als `` (content/ staat buiten webroot → 404). `processContent()` herschrijft nu lokale image/link URLs naar de `/-media/` endpoint die bestanden uit `content/` serveert met juiste MIME-type. Externe URLs (`http(s)://`), `/-media/`, `/-assets/`, `/themes/`, `/plugins/`, `/admin/`, `data:` en `mailto:` worden ongewijzigd gelaten. --- ## Technische details ### Nieuwe routes - `theme-edit` — thema bestandsbrowser editor - `theme-file-upload` — bestanden uploaden naar thema assets/ - `theme-file-delete` — bestand verwijderen uit thema (theme.json beschermd) - `theme-file-move` — bestand verplaatsen binnen thema (theme.json beschermd) - `theme-activate` — thema activeren (active_theme in config.json) - `theme-delete` — thema verwijderen (alleen niet-actief, niet-default) - `theme-scss` — SCSS compileren voor thema - `content-files` — content bestandsbrowser editor - `content-file-upload` — bestanden uploaden naar content/ - `content-file-delete` — bestand verwijderen uit content - `content-file-move` — bestand verplaatsen binnen content - `content-dir-create-in` — map aanmaken in content vanuit editor - `content-dir-rename-in` — map hernoemen in content vanuit editor - `content-dir-delete-in` — map verwijderen in content vanuit editor (alleen leeg) ### Nieuwe bestanden - `admin/theme/default/views/pages/theme-edit.twig` — thema editor met bestandsbrowser - `admin/theme/default/views/pages/theme-move-form.twig` — thema bestand verplaatsen - `admin/theme/default/views/pages/content-files.twig` — content editor met bestandsbrowser - `admin/theme/default/views/pages/content-move-form.twig` — content bestand verplaatsen - `admin/theme/default/views/pages/content-dir-rename-form.twig` — content map hernoemen - `docs/release-notes/v2.6.2.md` — dit release-verslag ### Gewijzigde bestanden (core) - `public/admin.php` — nieuwe routes + handlers (handleThemeEdit/FileUpload/Delete/Move/Activate/Delete/Scss, handleContentFiles/FileUpload/Delete/Move/DirCreateIn/DirRenameIn/DirDeleteIn, createUniformThemeStructure, copyDirRecursive, removeDirRecursive, scanEditorFiles + scanEditorFilesNode unified), handleTheme/handleThemeNew herschreven, handleMediaList uitgebreid met `?theme=` scope - `admin/src/AdminAuth.php` — site-admin rechten voor nieuwe theme routes; content-manager rechten voor nieuwe content routes - `admin/theme/default/views/pages/theme.twig` — bewerk/activeer/verwijder/compileer knoppen + SCSS-status badges - `admin/theme/default/views/pages/theme-new.twig` — base-theme keuze dropdown - `admin/theme/default/views/pages/_media-modal.twig` — `?theme=` scope support - `admin/theme/default/assets/js/editor-toolbar.js` — `twig` → `htmlmixed` mode toegevoegd - `cms/core/class/CodePressCMS.php` — `scanDirectory`/`searchInDirectory`/`scanForPageTitles` skippen nu `_` prefix; `processContent()` herschrijft lokale image/link URLs naar `/-media/` - `language/{nl,en,de}/admin.php` — ~45 nieuwe vertaalstrings (theme-editor + content-editor) - `guide/{nl,en}/admin-beheerder/thema-beheer.md` — volledig herschreven met thema-editor uitleg - `guide/{nl,en}/admin-beheerder/content-beheer.md` — volledig herschreven met content-editor uitleg - `TODO.md` — thema-editor en content-editor items aangevinkt --- ## Tests - **Pentest**: 30/30 tests geslaagd — 0 vulnerabilities - **WCAG 2.1 AA accessibility**: 25/25 tests geslaagd — 100% compliance - **PHP lint**: alle bestanden schoon (geen syntax errors) - **curl tests**: alle nieuwe routes getest (aanmaken, bewerken, opslaan, uploaden, verwijderen, verplaatsen, map aanmaken/hernoemen/verwijderen, SCSS compileren, thema activeren/verwijderen, thema kopiëren); path-traversal pogingen (delete/new_file/upload) allemaal geblokkeerd; default/active theme bescherming geverifieerd; theme.json verwijderen/plaatsen geblokkeerd; image-URL rewriting geverifieerd (relatief, /content/, subdir, extern ongewijzigd); `_`-map niet in frontend navigatie --- ## Bestanden gewijzigd sinds v2.6.1d 15 bestanden gewijzigd (core + admin theme + language + guide), ~2200 insertions, ~200 deletions.