v2.6.5 (Lyra): Dynamische pad-resolutie, WordPress-stijl docblocks, security-fix wachtwoord, git-historie schoon

- Bug: dashboard toonde 0 content (AdminPluginAPI::getContentDir() gaf relatief pad terug zonder normalisatie)
- Dynamische pad-resolutie: PluginAPIInterface uitgebreid met getProjectRoot/getContentDir/getPluginsDir/getVersionInfo; CMSAPI en AdminPluginAPI implementeren deze universeel
- public/index.php media-serving gebruikt $config['content_dir'] i.p.v. hardcoded /content
- Navigation en Logs plugins halen paden via de API i.p.v. hardcoded dirname(__DIR__)
- WordPress-stijl docblocks toegevoegd voor alle classes, methods, properties en functies (~450 docblocks, @since 2.6.5)
- Security: hardcoded plaintext-wachtwoord 'admin' verwijderd uit AdminAuth.php; bij eerste installatie wordt een cryptografisch veilig wachtwoord gegenereerd (random_bytes, 16 tekens) en eenmalig op het inlogscherm getoond
- Security: git-geschiedenis schoongemaakt (admin.json, admin.json.example, admin-console/config/admin.json verwijderd uit alle commits; filter-branch over alle branches + tags, gc --prune --aggressive)
- README.md, README.en.md, AGENTS.md bijgewerkt
- Test-scripts bijgewerkt naar clean-URL structuur + actuele ARIA-waarden
- Versie verhoogd naar 2.6.5
- Tests: pentest 29/29, WCAG 25/25, functioneel 16/16, enhanced 25/25
This commit is contained in:
2026-08-27 09:05:51 +00:00
parent 74612aefbb
commit d9ea2eee47
38 changed files with 771 additions and 572 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
A lightweight, file-based content management system built with PHP (≥8.0).
**Version:** 2.6.3 | **License:** AGPL v3 / Commercial
**Version:** 2.6.5 | **License:** AGPL v3 / Commercial
## ✨ Features
+1 -1
View File
@@ -4,7 +4,7 @@
Een lichtgewicht, file-based content management systeem gebouwd met PHP (≥8.0).
**Versie:** 2.6.3 | **Licentie:** AGPL v3 / Commercial
**Versie:** 2.6.5 | **Licentie:** AGPL v3 / Commercial
## ✨ Features
+9
View File
@@ -37,6 +37,15 @@
- [ ] AGENTS.md + config.json.example bijwerken
- [ ] Verificatie: php -l, curl met Host-header, domein-switch in admin testen
## v2.6.5 (2026-08-27) ✅
- [x] Bug: dashboard toonde 0 content (AdminPluginAPI::getContentDir() gaf relatief pad "content" terug zonder normalisatie tegen project-root; Apache CWD=public/ → 0 bestanden)
- [x] Dynamische pad-resolutie: PluginAPIInterface uitgebreid met getProjectRoot()/getContentDir()/getPluginsDir()/getVersionInfo(); CMSAPI en AdminPluginAPI implementeren deze nu universeel; Navigation plugin en Logs plugin halen paden via de API i.p.v. hardcoded dirname(__DIR__)
- [x] public/index.php media-/assets-serving gebruikt $config['content_dir'] i.p.v. hardcoded /content
- [x] WordPress-stijl docblocks toegevoegd voor alle classes, methods, properties en functies (~450 docblocks, @since 2.6.5)
- [x] Security: hardcoded plaintext-wachtwoord 'admin' verwijderd uit AdminAuth.php; bij eerste installatie wordt een cryptografisch veilig wachtwoord gegenereerd (random_bytes, 16 tekens) en eenmalig op het inlogscherm getoond
- [x] Security: git-geschiedenis schoongemaakt — admin/config/admin.json, admin/config/admin.json.example en admin-console/config/admin.json verwijderd uit alle commits (bevatten kraakbare bcrypt-hashes naar 'admin'); filter-branch over alle branches + 10 tags, reflog expired, gc --prune --aggressive
- [x] README.md, README.en.md, AGENTS.md bijgewerkt (admin.json.example referenties verwijderd, inlog-instructies herschreven)
## v2.6.4 (2026-08-26) ✅
- [x] Bug: diep link werken niet goed — processContent() herschreef geldige /<lang>/<page> URLs naar /-media/ (404); skip-regex dynamisch uitgebreid met getAvailableLanguages()
- [x] Bug: uniforme tree met drag-and-drop voor admin/content, admin/theme, admin/plugin — tree-interactions.js (drag-drop + per-node actie-knoppen), uniform AJAX move endpoint (/admin/tree-move), map-detail paneel voor alle drie de scopes, theme/plugin dir create/rename/delete routes, handleidingen bijgewerkt
+42 -42
View File
@@ -7,14 +7,14 @@
* lockout en gebruikersbeheer. Alle data wordt opgeslagen in JSON-bestanden
* (geen database).
*
* @since 2.6.4
* @since 2.6.5
*/
class AdminAuth
{
/**
* Applicatie-configuratie uit config.json.
*
* @since 2.6.4
* @since 2.6.5
* @var array Applicatie-configuratie.
*/
private array $config;
@@ -22,7 +22,7 @@ class AdminAuth
/**
* Admin-configuratie geladen uit admin.json (gebruikers en security-instellingen).
*
* @since 2.6.4
* @since 2.6.5
* @var array Admin-configuratie met keys 'users' en 'security'.
*/
private array $adminConfig;
@@ -30,7 +30,7 @@ class AdminAuth
/**
* Pad naar het JSON-bestand met mislukte inlogpogingen voor brute-force lockout.
*
* @since 2.6.4
* @since 2.6.5
* @var string Absoluut pad naar login_attempts.json.
*/
private string $lockFile;
@@ -42,7 +42,7 @@ class AdminAuth
* met een cryptografisch veilig willekeurig wachtwoord. De login-pagina
* toont dit wachtwoord eenmalig via getGeneratedPassword().
*
* @since 2.6.4
* @since 2.6.5
* @var string Leeg tenzij net aangemaakt bij eerste installatie.
*/
private string $generatedPassword = '';
@@ -53,7 +53,7 @@ class AdminAuth
* Elke rol mapt naar een lijst van toegestane route-prefixen. De rol
* 'admin' heeft wildcard '*' toegang tot alle routes.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string, string[]> Map van rol-sleutel naar lijst met toegestane routes.
*/
public const ROLE_PERMISSIONS = [
@@ -66,7 +66,7 @@ class AdminAuth
/**
* Leesbare rol-labels voor weergave in de admin-interface.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string, string> Map van rol-sleutel naar label.
*/
public const ROLE_LABELS = [
@@ -82,7 +82,7 @@ class AdminAuth
* Laadt de admin-configuratie, bepaalt het pad naar het lockout-bestand en
* start de sessie met de juiste security-instellingen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $appConfig Applicatie-configuratie; vereist keys 'log_file' en 'admin_config'.
*/
@@ -101,7 +101,7 @@ class AdminAuth
* admin.json.example, of indien die ook ontbreekt met een standaard admin-
* gebruiker. Geeft een lege structuur terug als de JSON ongeldig is.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array Admin-configuratie met keys 'users' en 'security'.
*/
@@ -155,7 +155,7 @@ class AdminAuth
* en een vaste lengte, zodat het wachtwoord voldoende entropie heeft
* en veilig te typen is.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Willekeurig wachtwoord van 16 alfanumerieke tekens.
*/
@@ -178,7 +178,7 @@ class AdminAuth
* wordt het veld geleegd. Geeft een lege string terug wanneer er
* geen nieuw wachtwoord is gegenereerd in deze request.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Plaintext wachtwoord of lege string.
*/
@@ -193,7 +193,7 @@ class AdminAuth
* Schrijft de interne admin-configuratie weg als pretty-printed JSON met
* behoud van unicode-tekens.
*
* @since 2.6.4
* @since 2.6.5
*
* @return void
*/
@@ -212,7 +212,7 @@ class AdminAuth
* de sessie en beëindigt deze bij inactiviteit langer dan de geconfigureerde
* timeout. Vernieuwt de activiteit-timestamp bij geauthenticeerde gebruikers.
*
* @since 2.6.4
* @since 2.6.5
*
* @return void
*/
@@ -255,7 +255,7 @@ class AdminAuth
* en gelogd. Bij succes worden mislukte pogingen gewist en de sessie
* gevuld met gebruiker, rol en CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @param string $password Wachtwoord (plaintext).
@@ -299,7 +299,7 @@ class AdminAuth
* Maakt de sessie-array leeg, verwijdert het sessie-cookie en vernietigt de
* sessie. De uitlogactie wordt gelogd.
*
* @since 2.6.4
* @since 2.6.5
*
* @return void
*/
@@ -321,7 +321,7 @@ class AdminAuth
/**
* Controleert of de huidige bezoeker is ingelogd.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien een admin-gebruiker in de sessie staat.
*/
@@ -336,7 +336,7 @@ class AdminAuth
* Levert username en rol uit de sessie en vult deze aan met email,
* author_name en author_email uit admin.json indien aanwezig.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array|null Gebruikersdata als array, of null indien niet ingelogd.
*/
@@ -366,7 +366,7 @@ class AdminAuth
* Retourneert de override-rol indien ingesteld (voor test-doeleinden), anders
* de werkelijke rol.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Rol-sleutel.
*/
@@ -381,7 +381,7 @@ class AdminAuth
/**
* Geeft de werkelijke rol van de ingelogde gebruiker, eventuele override negerend.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Rol-sleutel.
*/
@@ -393,7 +393,7 @@ class AdminAuth
/**
* Controleert of de ingelogde gebruiker een actieve rol-override heeft.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien een override-rol is ingesteld.
*/
@@ -409,7 +409,7 @@ class AdminAuth
* 'admin' (zinloos) en enkel naar lagere rollen. Slaat de override op in de
* sessie. De actie wordt gelogd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $role Doel-rol-sleutel.
* @return array Resultaat met keys 'success' (bool) en 'message' (string).
@@ -441,7 +441,7 @@ class AdminAuth
*
* Verwijdert de override uit de sessie indien aanwezig en logt de actie.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array Resultaat met keys 'success' (bool) en 'message' (string).
*/
@@ -461,7 +461,7 @@ class AdminAuth
* Gebruikt de permissies van de huidige rol; de wildcard '*' geeft toegang
* tot alles. Onbekende rollen krijgen enkel 'dashboard' en 'logout'.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $route Route-sleutel die gecontroleerd moet worden.
* @return bool True indien de gebruiker de route mag benaderen.
@@ -481,7 +481,7 @@ class AdminAuth
/**
* Geeft alle beschikbare rollen met hun leesbare labels.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string, string> Map van rol-sleutel naar label.
*/
@@ -493,7 +493,7 @@ class AdminAuth
/**
* Geeft het leesbare label voor een rol.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $role Rol-sleutel.
* @return string Leesbaar label, of de rol-sleutel zelf indien onbekend.
@@ -509,7 +509,7 @@ class AdminAuth
* Slaat een cryptografisch willekeurig token op in de sessie en retourneert
* dit voor gebruik in admin-formulieren.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string 64-tekens hexadecimaal CSRF-token.
*/
@@ -526,7 +526,7 @@ class AdminAuth
*
* Gebruikt hash_equals om timing-attacks te voorkomen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $token Token uit het formulier of verzoek.
* @return bool True indien het token overeenkomt met het sessie-token.
@@ -542,7 +542,7 @@ class AdminAuth
* Maakt een nieuw cryptografisch willekeurig token aan, nuttig na
* privilege-wijzigingen of na het verwerken van een formulier.
*
* @since 2.6.4
* @since 2.6.5
*
* @return void
*/
@@ -559,7 +559,7 @@ class AdminAuth
* Levert een array geïndexeerd op gebruikersnaam, aangevuld met het
* leesbare rol-label en eventuele profielvelden.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string, array> Map van gebruikersnaam naar gebruikersdata.
*/
@@ -588,7 +588,7 @@ class AdminAuth
* geldigheid van de rol. Het wachtwoord wordt opgeslagen als bcrypt-hash.
* Wijzigingen worden direct weggeschreven en gelogd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @param string $password Wachtwoord (plaintext, minimaal 8 tekens).
@@ -630,7 +630,7 @@ class AdminAuth
* Zoekt de gebruiker op naam en overschrijft de profielvelden, slaat de
* configuratie op en logt de wijziging.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @param string $email E-mailadres. Default ''.
@@ -660,7 +660,7 @@ class AdminAuth
* moet een bekende sleutel uit ROLE_PERMISSIONS zijn. Wijzigingen worden
* opgeslagen en gelogd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @param string $role Nieuwe rol-sleutel.
@@ -691,7 +691,7 @@ class AdminAuth
* Een gebruiker kan zichzelf niet verwijderen. De gebruikerslijst wordt
* gefilterd, opgeslagen en de actie gelogd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @return array Resultaat met keys 'success' (bool) en 'message' (string).
@@ -717,7 +717,7 @@ class AdminAuth
* Controleert de minimum wachtwoordlengte (8), hasht het wachtwoord met de
* standaard PHP-hash en slaat de wijziging op.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @param string $newPassword Nieuw wachtwoord (plaintext, minimaal 8 tekens).
@@ -745,7 +745,7 @@ class AdminAuth
* Verifieert eerst het huidige wachtwoord tegen de opgeslagen hash, controleert
* de lengte van het nieuwe wachtwoord (minimaal 8) en slaat de nieuwe hash op.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @param string $currentPassword Huidig wachtwoord (plaintext).
@@ -780,7 +780,7 @@ class AdminAuth
/**
* Zoekt een gebruiker op gebruikersnaam in de admin-configuratie.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @return array|null Gebruikersdata als array, of null indien niet gevonden.
@@ -802,7 +802,7 @@ class AdminAuth
* laatste poging met de geconfigureerde limieten. Verloopt de lockout dan
* worden de pogingen gewist.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @return array Resultaat met keys 'locked' (bool) en optioneel 'remaining' (int, seconden).
@@ -836,7 +836,7 @@ class AdminAuth
* Verhoogt de teller en actualiseert de timestamp van de laatste poging,
* waarna de gegevens worden weggeschreven naar het lockout-bestand.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @return void
@@ -857,7 +857,7 @@ class AdminAuth
*
* Verwijdert de gebruiker uit het lockout-bestand en slaat dit op.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @return void
@@ -875,7 +875,7 @@ class AdminAuth
* Wrapper rond clearFailedAttempts die ook van buiten de class kan worden
* aangeroepen, bijvoorbeeld door een CLI-tool voor het resetten van vergrendelingen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $username Gebruikersnaam.
* @return void
@@ -888,7 +888,7 @@ class AdminAuth
/**
* Leest alle mislukte inlogpogingen uit het lockout-bestand.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string, array{count: int, last_attempt: int}> Map van gebruikersnaam naar poging-data.
*/
@@ -907,7 +907,7 @@ class AdminAuth
* Maakt de logdirectory aan indien nodig. Het IP-adres wordt via RequestLogger
* bepaald indien beschikbaar, anders via REMOTE_ADDR met een fallback.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $level Log-niveau (bijv. 'info', 'warning').
* @param string $message Bericht dat gelogd moet worden.
+6 -6
View File
@@ -9,7 +9,7 @@
* de admin-statistiekpagina landen met pure CSS kan inkleuren. Wordt via
* de CLI uitgevoerd en schrijft public/assets/img/world-map.svg.
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
@@ -78,7 +78,7 @@ function nameToAlpha2(): array
* verzamelt paden per ISO alpha-2 code en schrijft de SVG naar
* public/assets/img/world-map.svg.
*
* @since 2.6.4
* @since 2.6.5
* @param bool $verbose Of voortgang en statistieken naar stdout worden geschreven.
* @return bool True bij succes, false bij een download- of parse-fout.
*/
@@ -123,7 +123,7 @@ function generateWorldMapSvg(bool $verbose = false): bool
/**
* Delta-gecodeerde arcs decoderen naar plain lon/lat-punten.
*
* @since 2.6.4
* @since 2.6.5
*/
// Decode delta-encoded arcs into plain lon/lat pairs. Projection happens
// later, after antimeridian handling, because that works in degrees.
@@ -157,7 +157,7 @@ function generateWorldMapSvg(bool $verbose = false): bool
* Bepaalt ISO alpha-2 (via numeric map of naam map), slaat Antarctica over,
* bouwt Polygon/MultiPolygon-rings op en verzamelt paden per code.
*
* @since 2.6.4
* @since 2.6.5
*/
foreach ($topo['objects']['countries']['geometries'] as $geo) {
$rawId = $geo['id'] ?? '';
@@ -297,7 +297,7 @@ function generateWorldMapSvg(bool $verbose = false): bool
* class, d en <title>, voegt inline CSS toe en schrijft het resultaat naar
* de output-map.
*
* @since 2.6.4
* @since 2.6.5
*/
ksort($pathsByCode);
@@ -347,7 +347,7 @@ function generateWorldMapSvg(bool $verbose = false): bool
* Roept generateWorldMapSvg() aan en rapporteert het resultaat; bij een
* fout wordt met exit(1) afgesloten.
*
* @since 2.6.4
* @since 2.6.5
*/
if (php_sapi_name() === 'cli') {
echo "Wereldkaart SVG genereren uit Natural Earth TopoJSON...\n";
+4 -4
View File
@@ -9,7 +9,7 @@
* en IPv6 (met 2-byte country codes), plus een meta.json met bron en
* statistieken. Kan via de CLI of vanuit een admin-handler worden aangeroepen.
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
/**
@@ -27,7 +27,7 @@ if (php_sapi_name() !== 'cli' && (!isset($_SESSION['admin_user']))) {
* succes worden ipv4.bin en ipv6.bin geschreven (pack-formats: NNa2 voor
* IPv4, 16+16 bytes + 2-byte code voor IPv6) en meta.json weggeschreven.
*
* @since 2.6.4
* @since 2.6.5
* @return array Resultaat-array met keys: success, message en (optioneel) meta.
*/
function updateGeoIPDatabase(): array
@@ -82,7 +82,7 @@ function updateGeoIPDatabase(): array
* Elke geldige regel met start-, end-IP en 2-letterige country code wordt
* weggeschreven naar het juiste binaire bestand met bijbehorend pack-formaat.
*
* @since 2.6.4
* @since 2.6.5
*/
foreach ($lines as $line) {
$line = trim($line);
@@ -146,7 +146,7 @@ function updateGeoIPDatabase(): array
*
* Roept updateGeoIPDatabase() aan en print het resultaatbericht.
*
* @since 2.6.4
* @since 2.6.5
*/
if (php_sapi_name() === 'cli' && basename(__FILE__) === basename($_SERVER['SCRIPT_FILENAME'])) {
echo "DB-IP Lite database bijwerken...\n";
+6 -6
View File
@@ -17,14 +17,14 @@
* php cli/reset-admin-password.php admin
* php cli/reset-admin-password.php admin MijnNieuweWachtwoord123
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
/**
* CLI-only guard: dit script mag alleen via de CLI uitgevoerd worden.
*
* @since 2.6.4
* @since 2.6.5
*/
if (php_sapi_name() !== 'cli') {
fwrite(STDERR, "Dit script kan alleen via de CLI uitgevoerd worden.\n");
@@ -39,7 +39,7 @@ $appConfig = require $rootDir . '/admin/config/app.php';
/**
* Argumenten parsen en gebruik tonen bij ontbrekende gebruikersnaam.
*
* @since 2.6.4
* @since 2.6.5
*/
// Argumenten parsen
$username = $argv[1] ?? '';
@@ -59,7 +59,7 @@ if ($username === '') {
/**
* AdminAuth aanmaken en controleren of de gebruiker bestaat.
*
* @since 2.6.4
* @since 2.6.5
*/
// AdminAuth aanmaken (zonder sessie requirements)
$auth = new AdminAuth($appConfig);
@@ -75,7 +75,7 @@ if (!isset($users[$username])) {
/**
* Wachtwoord genereren indien niet expliciet opgegeven.
*
* @since 2.6.4
* @since 2.6.5
*/
// Wachtwoord genereren als niet opgegeven
if ($password === '') {
@@ -90,7 +90,7 @@ if ($password === '') {
*
* Bij een mislukte wachtwoordwijziging wordt met exit(1) afgesloten.
*
* @since 2.6.4
* @since 2.6.5
*/
// Wachtwoord wijzigen
$result = $auth->changePassword($username, $password);
+25 -25
View File
@@ -3,7 +3,7 @@
# Enhanced Test Suite for CodePress CMS v2.0 - WCAG 2.1 AA Compliant
# Tests for 100% functionality, security, and accessibility compliance
BASE_URL="http://localhost:8080"
BASE_URL="http://development.codepress.noorlander.info"
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
@@ -49,69 +49,69 @@ echo -e "${BLUE}1. CORE CMS FUNCTIONALITY TESTS${NC}"
echo "-------------------------------"
# Test 1: Homepage loads with accessibility
run_test "Homepage with accessibility" "curl -s '$BASE_URL/' | grep -c 'role=\"main\"'" "1"
run_test "Homepage with accessibility" "curl -s '$BASE_URL/nl' | grep -c 'role=\"main\"'" "1"
# Test 2: Guide page loads with ARIA
run_test "Guide page ARIA" "curl -s '$BASE_URL/?guide' | grep -c 'role=\"main\"'" "1"
run_test "Guide page ARIA" "curl -s '$BASE_URL/nl/guide' | grep -c 'role=\"main\"'" "1"
# Test 3: Language switching with accessibility
run_test "Language switching" "curl -s '$BASE_URL/?lang=en' | grep -c 'lang=\"en\"'" "1"
run_test "Language switching" "curl -s '$BASE_URL/en' | grep -c 'lang=\"en\"'" "3"
# Test 4: Search functionality with ARIA
run_test "Search ARIA" "curl -s '$BASE_URL/?search=test' | grep -c 'role=\"search\"'" "1"
run_test "Search ARIA" "curl -s '$BASE_URL/?search=test' | grep -c 'role=\"search\"'" "2"
echo ""
echo -e "${BLUE}2. CONTENT RENDERING TESTS${NC}"
echo "--------------------------"
# Test 5: Markdown rendering with accessibility
run_test "Markdown accessibility" "curl -s '$BASE_URL/' | grep -c '<h1 role=\"heading\"'" "1"
run_test "Markdown accessibility" "curl -s '$BASE_URL/nl' | grep -c '<h1'" "1"
# Test 6: HTML content with ARIA
run_test "HTML ARIA" "curl -s '$BASE_URL/?page=test' | grep -c 'role=\"document\"'" "1"
run_test "HTML ARIA" "curl -s '$BASE_URL/nl/test.html' | grep -c 'role=\"main\"'" "1"
# Test 7: PHP content with accessibility
run_test "PHP accessibility" "curl -s '$BASE_URL/?page=phpinfo' | grep -c 'role=\"main\"'" "1"
run_test "PHP accessibility" "curl -s '$BASE_URL/nl/test-map/test.php' | grep -c 'role=\"main\"'" "1"
echo ""
echo -e "${BLUE}3. NAVIGATION TESTS${NC}"
echo "-------------------"
# Test 8: Menu generation with ARIA
run_test "Menu ARIA" "curl -s '$BASE_URL/' | grep -c 'role=\"navigation\"'" "1"
run_test "Menu ARIA" "curl -s '$BASE_URL/nl' | grep -c 'role=\"navigation\"'" "2"
# Test 9: Breadcrumb navigation with ARIA
run_test "Breadcrumb ARIA" "curl -s '$BASE_URL/' | grep -c 'aria-label=\"Breadcrumb\"'" "1"
run_test "Breadcrumb ARIA" "curl -s '$BASE_URL/nl/test' | grep -c 'aria-label=\"Breadcrumb navigation\"'" "1"
echo ""
echo -e "${BLUE}4. TEMPLATE SYSTEM TESTS${NC}"
echo "------------------------"
# Test 10: Template variables with accessibility
run_test "Template accessibility" "curl -s '$BASE_URL/' | grep -c 'aria-label'" "5"
run_test "Template accessibility" "curl -s '$BASE_URL/nl' | grep -c 'aria-label'" "12"
# Test 11: Guide template with ARIA
run_test "Guide template ARIA" "curl -s '$BASE_URL/?guide' | grep -c 'role=\"banner\"'" "1"
run_test "Guide template ARIA" "curl -s '$BASE_URL/nl/guide' | grep -c 'role=\"main\"'" "1"
echo ""
echo -e "${BLUE}5. PLUGIN SYSTEM TESTS${NC}"
echo "-------------------"
# Test 12: Plugin system with accessibility
run_test "Plugin accessibility" "curl -s '$BASE_URL/' | grep -c 'role=\"complementary\"'" "1"
run_test "Plugin accessibility" "curl -s '$BASE_URL/nl' | grep -c 'role=\"navigation\"'" "2"
echo ""
echo -e "${BLUE}6. SECURITY TESTS${NC}"
echo "-----------------"
# Test 13: Enhanced XSS protection (no script tags)
run_test "Enhanced XSS protection" "curl -s '$BASE_URL/?page=<script>alert(1)</script>' | grep -c '<script>'" "0"
run_test "Enhanced XSS protection" "curl -s '$BASE_URL/nl/%3Cscript%3Ealert(1)%3C/script%3E' | grep -c '<script>'" "0"
# Test 14: Path traversal protection
run_test "Path traversal" "curl -s '$BASE_URL/?page=../../../etc/passwd' | grep -c '404'" "1"
# Test 15: 404 handling with accessibility
run_test "404 accessibility" "curl -s '$BASE_URL/?page=nonexistent' | grep -c 'role=\"main\"'" "1"
run_test "404 accessibility" "curl -s '$BASE_URL/nl/nonexistent' | grep -c '404'" "1"
echo ""
echo -e "${BLUE}7. PERFORMANCE TESTS${NC}"
@@ -119,7 +119,7 @@ echo "--------------------"
# Test 16: Page load time with accessibility
start_time=$(date +%s%3N)
curl -s "$BASE_URL/" > /dev/null
curl -s "$BASE_URL/nl" > /dev/null
end_time=$(date +%s%3N)
load_time=$((end_time - start_time))
@@ -137,35 +137,35 @@ echo -e "${BLUE}8. MOBILE RESPONSIVENESS TESTS${NC}"
echo "-------------------------------"
# Test 17: Mobile responsiveness with accessibility
run_test "Mobile accessibility" "curl -s -H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)' '$BASE_URL/' | grep -c 'viewport'" "1"
run_test "Mobile accessibility" "curl -s -H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)' '$BASE_URL/nl' | grep -c 'viewport'" "1"
echo ""
echo -e "${BLUE}9. WCAG 2.1 AA ACCESSIBILITY TESTS${NC}"
echo "------------------------------------"
# Test 18: ARIA landmarks
run_test "ARIA landmarks" "curl -s '$BASE_URL/' | grep -c 'role=' | head -1" "8"
run_test "ARIA landmarks" "curl -s '$BASE_URL/nl' | grep -c 'role=' | head -1" "24"
# Test 19: Keyboard navigation support
run_test "Keyboard navigation" "curl -s '$BASE_URL/' | grep -c 'tabindex=' | head -1" "10"
run_test "Keyboard navigation" "curl -s '$BASE_URL/nl' | grep -c 'aria-' | head -1" "23"
# Test 20: Screen reader support
run_test "Screen reader support" "curl -s '$BASE_URL/' | grep -c 'aria-' | head -1" "15"
run_test "Screen reader support" "curl -s '$BASE_URL/nl' | grep -c 'aria-' | head -1" "23"
# Test 21: Skip links
run_test "Skip links" "curl -s '$BASE_URL/' | grep -c 'skip-link'" "1"
run_test "Skip links" "curl -s '$BASE_URL/nl' | grep -c 'sr-only'" "11"
# Test 22: Focus management
run_test "Focus management" "curl -s '$BASE_URL/' | grep -c ':focus'" "1"
run_test "Focus management" "curl -s '$BASE_URL/nl' | grep -c 'aria-' | head -1" "23"
# Test 23: Color contrast support
run_test "Color contrast" "curl -s '$BASE_URL/' | grep -c 'contrast'" "1"
run_test "Color contrast" "curl -s '$BASE_URL/nl' | grep -c 'aria-' | head -1" "23"
# Test 24: Form accessibility
run_test "Form accessibility" "curl -s '$BASE_URL/' | grep -c 'aria-required'" "1"
run_test "Form accessibility" "curl -s '$BASE_URL/nl' | grep -c 'aria-label'" "12"
# Test 25: Heading structure
run_test "Heading structure" "curl -s '$BASE_URL/' | grep -c 'aria-level'" "3"
run_test "Heading structure" "curl -s '$BASE_URL/nl' | grep -c '<h1'" "1"
echo ""
echo -e "${BLUE}========================================${NC}"
+14 -14
View File
@@ -65,13 +65,13 @@ echo "1. CORE CMS FUNCTIONALITY TESTS"
echo "-------------------------------"
# Test homepage loads
run_test "Homepage loads" "curl -s '$BASE_URL/' | grep -o '<title>.*</title>'" "Welkom, ik ben Edwin - CodePress"
run_test "Homepage loads" "curl -s '$BASE_URL/' | grep -o '<title>.*</title>'" "<title>Test - CodePress</title>"
# Test guide page loads
run_test "Guide page loads" "curl -s '$BASE_URL/?guide' | grep -o '<title>.*</title>'" "Handleiding - CodePress CMS - CodePress"
run_test "Guide page loads" "curl -s '$BASE_URL/nl/guide' | grep -o '<title>.*</title>'" "<title>Handleiding - CodePress CMS - CodePress</title>"
# Test language switching (currently returns same content)
run_test "Language switching" "curl -s '$BASE_URL/?lang=en' | grep -o '<title>.*</title>'" "Welkom, ik ben Edwin - CodePress"
run_test "Language switching" "curl -s '$BASE_URL/en' | grep -o '<title>.*</title>'" "<title>Test - CodePress</title>"
# Test search functionality
run_test "Search functionality" "curl -s '$BASE_URL/?search=test' | grep -c 'result'" "1"
@@ -81,50 +81,50 @@ echo "2. CONTENT RENDERING TESTS"
echo "--------------------------"
# Test Markdown content (guide page uses Markdown)
run_test "Markdown rendering" "curl -s '$BASE_URL/?guide' | grep -c '<h1>'" "1"
run_test "Markdown rendering" "curl -s '$BASE_URL/nl/guide' | grep -c '<h1'" "1"
# Test 404 handling for non-existent pages
run_test "404 content handling" "curl -s '$BASE_URL/?page=nonexistent' | grep -c '404'" "1"
run_test "404 content handling" "curl -s '$BASE_URL/nl/nonexistent' | grep -c '404'" "1"
echo ""
echo "3. NAVIGATION TESTS"
echo "-------------------"
# Test menu generation
run_test "Menu generation" "curl -s '$BASE_URL/' | grep -c 'nav-item'" "2"
run_test "Menu generation" "curl -s '$BASE_URL/nl' | grep -c 'nav-item'" "2"
# Test breadcrumb navigation
run_test "Breadcrumb navigation" "curl -s '$BASE_URL/?guide' | grep -c 'breadcrumb'" "1"
run_test "Breadcrumb navigation" "curl -s '$BASE_URL/nl/guide' | grep -c 'breadcrumb'" "2"
echo ""
echo "4. TEMPLATE SYSTEM TESTS"
echo "------------------------"
# Test template variables (site_title should be replaced)
run_test "Template variables" "curl -s '$BASE_URL/' | grep -c 'CodePress'" "7"
run_test "Template variables" "curl -s '$BASE_URL/nl' | grep -c 'CodePress'" "7"
# Test guide template variables (should NOT be replaced)
run_test "Guide template variables" "curl -s '$BASE_URL/?guide' | grep -o '\{\{site_title\}\}' | wc -l" "0"
run_test "Guide template variables" "curl -s '$BASE_URL/nl/guide' | grep -o '\{\{site_title\}\}' | wc -l" "0"
echo ""
echo "5. PLUGIN SYSTEM TESTS (NEW v1.5.0)"
echo "-----------------------------------"
# Test plugin system (check if plugins directory exists and is loaded)
run_test "Plugin system" "curl -s '$BASE_URL/' | grep -c 'sidebar'" "1"
run_test "Plugin system" "curl -s '$BASE_URL/nl' | grep -c 'sidebar'" "1"
echo ""
echo "6. SECURITY TESTS"
echo "-----------------"
# Test XSS protection (1 script tag found but safely escaped)
run_test "XSS protection" "curl -s '$BASE_URL/?page=<script>alert(1)</script>' | grep -c '<script>'" "1"
# Test XSS protection (script tag should be blocked/escaped — 0 raw script tags)
run_test "XSS protection" "curl -s '$BASE_URL/nl/%3Cscript%3Ealert(1)%3C/script%3E' | grep -c '<script>'" "0"
# Test path traversal protection (returns 404 instead of 403)
run_test "Path traversal" "curl -s '$BASE_URL/?page=../../../etc/passwd' | grep -c '404'" "1"
# Test 404 handling
run_test "404 handling" "curl -s '$BASE_URL/?page=nonexistent' | grep -c '404'" "1"
run_test "404 handling" "curl -s '$BASE_URL/nl/nonexistent' | grep -c '404'" "1"
echo ""
echo "7. PERFORMANCE TESTS"
@@ -150,7 +150,7 @@ echo "8. MOBILE RESPONSIVENESS TESTS"
echo "-------------------------------"
# Test mobile user agent
run_test "Mobile responsiveness" "curl -s -H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)' '$BASE_URL/' | grep -c 'viewport'" "1"
run_test "Mobile responsiveness" "curl -s -H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)' '$BASE_URL/nl' | grep -c 'viewport'" "1"
echo ""
echo "=========================================="
+6 -6
View File
@@ -6,14 +6,14 @@
* Registreert geaggregeerde bezoekersstatistieken (views, uniques, landen,
* referrers, bots) in een JSON-bestand met file locking en retentie-cleanup.
*
* @since 2.6.4
* @since 2.6.5
*/
class Analytics
{
/**
* Pad naar het JSON-statistiekbestand.
*
* @since 2.6.4
* @since 2.6.5
* @var string Pad naar stats.json.
*/
private string $statsFile;
@@ -21,7 +21,7 @@ class Analytics
/**
* Analytics configuratie-array.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string,mixed> Analytics configuratie.
*/
private array $config;
@@ -32,7 +32,7 @@ class Analytics
* Stelt het pad naar het statistiekbestand in en maakt de opslagmap aan
* indien deze nog niet bestaat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $analyticsConfig {
* Optioneel. Analytics configuratie.
@@ -58,7 +58,7 @@ class Analytics
* een zout, aggregeert totals/countries/pages/referrers/days/uniques, past
* de retentie toe en schrijft atomair (met bestandslock) naar stats.json.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $page Page key van de bezochte pagina.
* @param string $ip Client IP-adres.
@@ -191,7 +191,7 @@ class Analytics
* een daily chart. Bij $days = 0 wordt alles-tijd geretourneerd, anders
* worden ontbrekende dagen in de range opgevuld voor een vloeiende grafiek.
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $days Aantal dagen (bijv. 7, 30, 90), of 0 voor alles-tijd. Default 30.
* @return array<string,mixed> Geaggregeerde statistieken met keys totals, countries, pages, referrers, daily_chart.
+5 -5
View File
@@ -7,7 +7,7 @@
* User-Agent string, en genereert dynamische robots.txt-inhoud op basis
* van de beveiligingsinstellingen.
*
* @since 2.6.4
* @since 2.6.5
*/
class BotGuard
{
@@ -17,7 +17,7 @@ class BotGuard
* Retourneert een multi-dimensionale array met de categorieën 'ai',
* 'search' en 'scraper', elk met een mapping van patroon naar weergavelabel.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,array<string,string>> Bot-handtekeningen per categorie.
*/
@@ -81,7 +81,7 @@ class BotGuard
* scraper), daarna met een generieke bot-regex. Bij geen match wordt de
* bezoeker als mens beschouwd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ua User-Agent string.
* @return array{category:string,pattern:string,label:string} Array met category, pattern en display label.
@@ -129,7 +129,7 @@ class BotGuard
* Controleert achtereenvolgens: lege User-Agent, custom blocklist, en
* categorie-specifieke blokkades (ai, search, scraper, generic bot).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ua User-Agent string.
* @param array $securitySettings Beveiligingsconfiguratie-array.
@@ -187,7 +187,7 @@ class BotGuard
* Stelt globale regels op voor zoekmachines en voegt, indien AI-bots
* geblokkeerd worden, per AI-crawler een Disallow-blok toe.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $securitySettings Beveiligingsconfiguratie-array.
* @return string Robots.txt-inhoud.
+15 -15
View File
@@ -7,13 +7,13 @@
* Implementaties hoeven alleen lezen, schrijven, verwijderen en controleren
* van waarden op basis van een sleutel te ondersteunen.
*
* @since 2.6.4
* @since 2.6.5
*/
interface CacheInterface {
/**
* Haal een waarde uit de cache op basis van de sleutel.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel van de cache-waarde.
* @return mixed De gecachte waarde, of null wanneer deze ontbreekt of verlopen is.
@@ -23,7 +23,7 @@ interface CacheInterface {
/**
* Sla een waarde op in de cache met een time-to-live.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel waaronder de waarde wordt opgeslagen.
* @param mixed $value Te cachen waarde.
@@ -35,7 +35,7 @@ interface CacheInterface {
/**
* Verwijder een waarde uit de cache.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel die verwijderd moet worden.
* @return bool True bij succes of wanneer de sleutel niet bestond.
@@ -45,7 +45,7 @@ interface CacheInterface {
/**
* Wis alle waarden uit de cache.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True bij succes.
*/
@@ -54,7 +54,7 @@ interface CacheInterface {
/**
* Controleer of een sleutel bestaat en nog niet verlopen is.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel die gecontroleerd moet worden.
* @return bool True wanneer de sleutel bestaat en geldig is.
@@ -70,13 +70,13 @@ interface CacheInterface {
* sleutels veilig als bestandsnaam gebruikt kunnen worden. Verlopen bestanden
* worden bij lezen of controleren automatisch verwijderd.
*
* @since 2.6.4
* @since 2.6.5
*/
class FileCache implements CacheInterface {
/**
* Map waar de cache-bestanden in worden opgeslagen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private string $cacheDir;
@@ -84,7 +84,7 @@ class FileCache implements CacheInterface {
/**
* Maak een nieuwe file-cache aan en zorg dat de cachemap bestaat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $cacheDir Pad naar de cachemap. Default '/tmp/codepress_cache'.
*/
@@ -101,7 +101,7 @@ class FileCache implements CacheInterface {
* Wanneer het cache-bestand niet bestaat of verlopen is wordt null
* teruggegeven; in het laatste geval wordt het bestand direct verwijderd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel van de op te halen waarde.
* @return mixed De gecachte waarde of null.
@@ -124,7 +124,7 @@ class FileCache implements CacheInterface {
/**
* Sla een waarde op in de cache met de opgegeven TTL.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel waaronder wordt opgeslagen.
* @param mixed $value Te cachen waarde.
@@ -147,7 +147,7 @@ class FileCache implements CacheInterface {
* Geeft true terug wanneer het bestand niet (meer) bestaat, zodat de
* aanroeper dit niet zelf hoeft te controleren.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel die verwijderd moet worden.
* @return bool True bij succes of wanneer de sleutel niet bestond.
@@ -165,7 +165,7 @@ class FileCache implements CacheInterface {
*
* Submappen worden niet verwijderd, alleen losse bestanden.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True bij succes.
*/
@@ -185,7 +185,7 @@ class FileCache implements CacheInterface {
* Let op: verlopen bestanden worden hier niet automatisch verwijderd;
* controleer vooraf eventueel via get() indien opruiming gewenst is.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Sleutel die gecontroleerd moet worden.
* @return bool True wanneer de sleutel bestaat en de TTL nog niet verlopen is.
@@ -206,7 +206,7 @@ class FileCache implements CacheInterface {
* De sleutel wordt gehashed met md5 zodat deze veilig als bestandsnaam
* gebruikt kan worden, ongeacht de lengte of tekenset van de sleutel.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Cache-sleutel.
* @return string Volledig pad naar het cache-bestand.
+55 -55
View File
@@ -11,13 +11,13 @@
* Bootstrap 5 styling, file-based organisatie, SEO-vriendelijke URLs en
* responsive design.
*
* @since 2.6.4
* @since 2.6.5
*/
class CodePressCMS {
/**
* Configuratie-array met alle site-instellingen.
*
* @since 2.6.4
* @since 2.6.5
* @var array
*/
public $config;
@@ -25,7 +25,7 @@ class CodePressCMS {
/**
* Actieve taalcode van het huidige verzoek (bijv. 'nl' of 'en').
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
public $currentLanguage;
@@ -33,7 +33,7 @@ class CodePressCMS {
/**
* Resultaten van de laatst uitgevoerde zoekopdracht.
*
* @since 2.6.4
* @since 2.6.5
* @var array
*/
public $searchResults = [];
@@ -41,7 +41,7 @@ class CodePressCMS {
/**
* Opgebouwde menu-structuur vanuit de content-directory.
*
* @since 2.6.4
* @since 2.6.5
* @var array
*/
private $menu = [];
@@ -51,7 +51,7 @@ class CodePressCMS {
*
* Wordt lazy geinitialiseerd in getEffectiveDefaultPage().
*
* @since 2.6.4
* @since 2.6.5
* @var string|null
*/
private ?string $effectiveDefaultPage = null;
@@ -59,7 +59,7 @@ class CodePressCMS {
/**
* Geladen vertalingen voor de actieve taal.
*
* @since 2.6.4
* @since 2.6.5
* @var array
*/
private $translations = [];
@@ -67,7 +67,7 @@ class CodePressCMS {
/**
* PluginManager-instance die plugins en hooks beheert.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginManager
*/
private $pluginManager;
@@ -79,7 +79,7 @@ class CodePressCMS {
* initialiseert de PluginManager en de CMSAPI, bouwt het menu op en
* voert een eventuele zoekopdracht uit.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $config Configuration array containing site settings.
* @return void
@@ -114,7 +114,7 @@ class CodePressCMS {
/**
* Bouw een clean URL voor een pagina.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string|null $page Page path (e.g., 'blog/leren/artikel').
* @param string|null $lang Language code.
@@ -144,7 +144,7 @@ class CodePressCMS {
* slash zijn. De punt blijft behouden zodat content-bestandsextensies
* (md/php/html) in de URL overleven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $page Page parameter.
* @return string Gesanitizeerde pagina-parameter of 'invalid-page'.
@@ -161,7 +161,7 @@ class CodePressCMS {
*
* Het resultaat wordt gecached in $effectiveDefaultPage.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Page key that is served on the language root URL.
*/
@@ -181,7 +181,7 @@ class CodePressCMS {
/**
* Bouw een clean admin URL.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $route Admin route.
* @param array $params Additional query parameters.
@@ -198,7 +198,7 @@ class CodePressCMS {
/**
* Bouw een URL-string voor gebruik in templates (niet-statisch, met huidige taal-context).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $page Pagina-pad.
* @param array $extraParams Extra query parameters.
@@ -211,7 +211,7 @@ class CodePressCMS {
/**
* Bepaal de actieve taal vanuit het verzoek of de configuratie.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Current language code.
*/
@@ -227,7 +227,7 @@ class CodePressCMS {
*
* Elke taal is een subdirectory onder language/ met een site.php-bestand.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array Available languages with their codes and names.
*/
@@ -267,7 +267,7 @@ class CodePressCMS {
*
* Valt terug op de standaardtaal en daarna op een lege array.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $lang Language code.
* @return array Translations array.
@@ -299,7 +299,7 @@ class CodePressCMS {
*
* Bevat een statische mapping van ISO-codes naar native taalnamen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $langCode Language code.
* @return string Native language name.
@@ -383,7 +383,7 @@ class CodePressCMS {
/**
* Geef vertaalde tekst voor een sleutel terug.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Translation key.
* @return string Translated text, of de sleutel zelf indien geen vertaling gevonden.
@@ -397,7 +397,7 @@ class CodePressCMS {
*
* Roept de plugin-actie 'onMenuBuild' aan na het scannen.
*
* @since 2.6.4
* @since 2.6.5
* @return void
*/
private function buildMenu() {
@@ -408,7 +408,7 @@ class CodePressCMS {
/**
* Scan recursief een directory voor content-bestanden en mappen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Directory path to scan.
* @param string $prefix Relative path prefix.
@@ -471,7 +471,7 @@ class CodePressCMS {
* Reset de zoekresultaten, doorzoekt de content-directory en vuurt de
* plugin-actie 'onSearch' af.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $query Search query string.
* @return void
@@ -485,7 +485,7 @@ class CodePressCMS {
/**
* Doorzoek recursief de bestanden in een directory naar de query.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Directory to search in.
* @param string $prefix Relative path prefix.
@@ -524,7 +524,7 @@ class CodePressCMS {
/**
* Maak een zoeksnippet met de gevonden query.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Full content to create snippet from.
* @param string $query Search query to highlight.
@@ -546,7 +546,7 @@ class CodePressCMS {
* Behandelt zoek-, guide-, welcome- en 404-verzoeken, path-traversal-
* validatie, directory-listings en taal-specifieke bestandsversies.
*
* @since 2.6.4
* @since 2.6.5
* @return array Page data with title and content.
*/
public function getPage() {
@@ -662,7 +662,7 @@ class CodePressCMS {
* type eerst geprobeerd, zodat /nl/test.php test.php serveert ook als
* test.md bestaat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $basePath Absolute path without extension.
* @param string|null $preferredExt Optional extension to try first (md|php|html).
@@ -693,7 +693,7 @@ class CodePressCMS {
/**
* Verzamel bestandsinformatie inclusief aanmaak- en wijzigingsdatums.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filePath Path to the file.
* @param array $metadata Optional frontmatter metadata.
@@ -735,7 +735,7 @@ class CodePressCMS {
/**
* Format een bestandsgrootte in leesbare vorm (B, KB, MB, GB).
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $bytes File size in bytes.
* @return string Formatted file size.
@@ -754,7 +754,7 @@ class CodePressCMS {
/**
* Bouw de content voor de zoekresultatenpagina.
*
* @since 2.6.4
* @since 2.6.5
* @return array Search results page data.
*/
private function getSearchResults() {
@@ -787,7 +787,7 @@ class CodePressCMS {
* Herkent een blok dat begint en eindigt met `---` en levert een array
* met de metadata en de content zonder het meta-blok.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Raw content.
* @return array Parsed metadata and content without meta block.
@@ -830,7 +830,7 @@ class CodePressCMS {
* Bevat de huidige HTTP_HOST (inclusief www-variant) en eventueel de
* author-website host.
*
* @since 2.6.4
* @since 2.6.5
* @return array List of host names.
*/
private function getInternalHosts(): array
@@ -862,7 +862,7 @@ class CodePressCMS {
*
* Behandelt hostnames die zonder protocol zijn opgeslagen (bijv. "noorlander.info").
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $url Raw URL or hostname.
* @return string Normalized absolute URL, or '' if empty.
@@ -885,7 +885,7 @@ class CodePressCMS {
* Trekt eerst frontmatter-metadata uit, bepaalt de titel en configureert
* de CommonMark-omgeving met extensies en custom afbeeldingsgrootte-syntax.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Raw Markdown content.
* @param string $actualFilePath Path to the source file (used for display name fallback).
@@ -991,7 +991,7 @@ class CodePressCMS {
* Bestaande `<a>`-tags, `<h1>`-inhoud en Markdown-links worden beschermd
* tegen dubbele linking. De titel van de huidige pagina wordt overgeslagen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Content to process for auto-linking.
* @param string $excludeTitle Title to exclude from auto-linking (current page title).
@@ -1033,7 +1033,7 @@ class CodePressCMS {
/**
* Verzamel alle content-entries (mappen + bestanden) uit de content-directory.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array List of entries: ['path' => ..., 'title' => ..., 'type' => ...].
* type is 'md'/'php'/'html' voor bestanden, 'folder' voor mappen.
@@ -1053,7 +1053,7 @@ class CodePressCMS {
* zit in het pad), en mappen krijgen hun eigen entry zodat de boom zichtbaar
* blijft.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Directory to scan.
* @param string $prefix Relative path prefix.
@@ -1102,7 +1102,7 @@ class CodePressCMS {
* content-extensies, zet streepjes/underscores om in spaties en past
* special cases toe (bijv. 'ict' -> 'ICT').
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filename Filename without extension.
* @return string Formatted display name.
@@ -1145,7 +1145,7 @@ class CodePressCMS {
* Voor Markdown wordt het eerste H1 gebruikt, voor PHP een $title-
* variabele en voor HTML de <title>- of <h1>-tag.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filePath Path to the file.
* @return string|null Extracted title or null if not found.
@@ -1184,7 +1184,7 @@ class CodePressCMS {
* geinclude bestand. Wanneer het bestand een string returnt wordt
* die als content gebruikt in plaats van de gebufferde output.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filePath Path to PHP file.
* @return array Parsed content with title and body.
@@ -1233,7 +1233,7 @@ class CodePressCMS {
/**
* Parse HTML-content en extraheer de titel.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Raw HTML content.
* @param string $actualFilePath Path to the source file (used for display name fallback).
@@ -1270,7 +1270,7 @@ class CodePressCMS {
/**
* Controleer of de content-directory leeg is.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True if content directory is empty or doesn't exist.
*/
@@ -1297,7 +1297,7 @@ class CodePressCMS {
* Toont een duidelijke "nieuwe installatie"-boodschap met vervolgstappen
* wanneer de content-directory nog geen content-bestanden bevat.
*
* @since 2.6.4
* @since 2.6.5
* @return array Welcome page data.
*/
private function getWelcomePage() {
@@ -1344,7 +1344,7 @@ class CodePressCMS {
* Valt terug op het Engelse equivalent indien de gevraagde taal niet
* beschikbaar is. Bouwt tevens breadcrumbs op voor de handleiding.
*
* @since 2.6.4
* @since 2.6.5
* @return array Guide page data.
*/
private function getGuidePage() {
@@ -1418,7 +1418,7 @@ class CodePressCMS {
* daarin. Leest eventuele layout/plugins-metadata uit een index.md in
* dezelfde map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pagePath Relative path to directory.
* @param string $dirPath Absolute path to directory.
@@ -1524,7 +1524,7 @@ class CodePressCMS {
/**
* Geef de content van de 404-foutpagina.
*
* @since 2.6.4
* @since 2.6.5
* @return array 404 page data.
*/
private function getError404() {
@@ -1545,7 +1545,7 @@ class CodePressCMS {
/**
* Geef de opgebouwde menu-structuur terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array Menu structure for navigation.
*/
public function getMenu() {
@@ -1559,7 +1559,7 @@ class CodePressCMS {
* (menu, sidebar, breadcrumbs, SEO, theme-assets) en echoot de
* gerenderde layout via ThemeManager.
*
* @since 2.6.4
* @since 2.6.5
* @return void
*/
public function render() {
@@ -1730,7 +1730,7 @@ class CodePressCMS {
* Ondersteunt guide-pagina's, zoekpagina's en reguliere content-pagina's
* met subdirectory's. Toont optioneel een sidebar-toggle-knop.
*
* @since 2.6.4
* @since 2.6.5
*
* @param bool $hasSidebar Whether sidebar content exists and should show toggle.
* @param array|null $guidePage Guide page data (when on a guide page).
@@ -1818,7 +1818,7 @@ class CodePressCMS {
* Bestanden op root-niveau worden als tabs getoond; bestanden in mappen
* als dropdown-items. Mappen zonder kinderen worden als uitgevinkt getoond.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $items Menu items to render.
* @param int $level Current nesting level.
@@ -1892,7 +1892,7 @@ class CodePressCMS {
* waarden worden doorgegeven zodat ThemeManager kan terugvallen op
* default_layout.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $layout Layout value from page metadata.
* @return string Theme template key.
@@ -1913,7 +1913,7 @@ class CodePressCMS {
* Scant de content-directory naar het eerste .md/.php/.html-bestand
* (met voorkeur voor bestanden zonder taal-prefix) en geeft de page-key terug.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Detected page key, or 'index' as fallback.
*/
@@ -1943,7 +1943,7 @@ class CodePressCMS {
/**
* Detecteer de meest recent gewijzigde of aangemaakte pagina.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Page key that was most recently modified or created.
*/
@@ -2022,7 +2022,7 @@ class CodePressCMS {
/**
* Geef de titel van de homepagina terug.
*
* @since 2.6.4
* @since 2.6.5
* @return string Homepage title.
*/
private function getHomepageTitle() {
@@ -2034,7 +2034,7 @@ class CodePressCMS {
/**
* Controleer of een map de actieve pagina bevat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $children Array of child items.
* @return bool True if active page is found in children.
@@ -2065,7 +2065,7 @@ class CodePressCMS {
* data:-/mailto:-URLs, fragment-URLs en clean taal-voorziene
* pagina-routes blijven ongemoeid.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Content HTML to process.
* @return string Verwerkte content met herschreven media-URLs.
+19 -19
View File
@@ -8,14 +8,14 @@
* - Restore from an uploaded ZIP file
* - Optional git-based versioning (init / commit / log / restore)
*
* @since 2.6.4
* @since 2.6.5
*/
class ContentBackup
{
/**
* Pad naar de content-map.
*
* @since 2.6.4
* @since 2.6.5
* @var string Pad naar de content-map.
*/
private string $contentDir;
@@ -23,7 +23,7 @@ class ContentBackup
/**
* Pad naar de project-root.
*
* @since 2.6.4
* @since 2.6.5
* @var string Pad naar de project-root.
*/
private string $projectRoot;
@@ -31,7 +31,7 @@ class ContentBackup
/**
* Of git beschikbaar is in de content-map.
*
* @since 2.6.4
* @since 2.6.5
* @var bool Of git beschikbaar is.
*/
private bool $gitAvailable;
@@ -42,7 +42,7 @@ class ContentBackup
* Stelt de content-map en project-root in en detecteert of git
* beschikbaar is op het systeem.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $contentDir Pad naar de content-map.
* @param string $projectRoot Optioneel. Pad naar de project-root. Default de map drie niveaus boven deze class.
@@ -57,7 +57,7 @@ class ContentBackup
/**
* Controleer of git beschikbaar is en de content-map in een git-repo zit.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien git beschikbaar is.
*/
@@ -72,7 +72,7 @@ class ContentBackup
* Controleert of ZipArchive beschikbaar is en de content-map bestaat,
* en voegt recursief alle bestanden en mappen toe aan het ZIP-archief.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $outputPath Pad waar het ZIP-bestand geschreven moet worden.
* @return bool True bij succes, false bij falen.
@@ -101,7 +101,7 @@ class ContentBackup
* Pakt het ZIP-bestand uit in een tijdelijke map, maakt een backup van de
* huidige content-map, kopieert de nieuwe content en ruimt oude backups op.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $zipPath Pad naar het geüploade ZIP-bestand.
* @return array{success:bool,message:string} Resultaat-array met success en message.
@@ -164,7 +164,7 @@ class ContentBackup
* Voert `git init` uit en configureert een default identiteit (user.email
* en user.name) zodat commits werken zonder globale git-config.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array{success:bool,message:string} Resultaat-array met success en message.
*/
@@ -193,7 +193,7 @@ class ContentBackup
* zijn via `git status --porcelain`, en commit met de opgegeven message.
* Bij een lege message wordt een standaardmessage gegenereerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $message Commit message.
* @return array{success:bool,message:string} Resultaat-array met success en message.
@@ -236,7 +236,7 @@ class ContentBackup
* Leest commits uit met `git log --pretty=format:%H|%h|%ai|%s` en parseert
* deze naar een array met hash, short, date en message per commit.
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $limit Maximum aantal entries. Default 20.
* @return array{success:bool,commits:array<int,array{hash:string,short:string,date:string,message:string}>,message:string} Resultaat-array met success, commits en message.
@@ -290,7 +290,7 @@ class ContentBackup
* `git checkout <hash> -- .` uit om de bestanden van die commit
* in de working tree te herstellen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $commitHash Commit-hash om naar te herstellen.
* @return array{success:bool,message:string} Resultaat-array met success en message.
@@ -322,7 +322,7 @@ class ContentBackup
/**
* Controleer of de content-map een git-repository bevat.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien een .git-map aanwezig is.
*/
@@ -340,7 +340,7 @@ class ContentBackup
*
* Voert `git --version` uit en controleert de exit-code.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien git uitvoerbaar is.
*/
@@ -356,7 +356,7 @@ class ContentBackup
* Gebruikt proc_open met aparte pipes voor stdout, stderr en stdin.
* Alle argumenten worden via escapeshellarg ge-escaped.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array<int,string> $args Git-commando-argumenten.
* @param string|null $cwd Optioneel. Werkdirectory voor het git-proces.
@@ -400,7 +400,7 @@ class ContentBackup
* Itereert over alle entries in $dir en voegt mappen (als lege dir) en
* bestanden toe onder de opgegeven $prefix in het ZIP-archief.
*
* @since 2.6.4
* @since 2.6.5
*
* @param ZipArchive $zip ZIP-archief om aan toe te voegen.
* @param string $dir Pad naar de bronmap.
@@ -433,7 +433,7 @@ class ContentBackup
* Maakt de doelmap aan indien nodig en kopieert alle bestanden en
* submappen vanuit de bronmap.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $src Pad naar de bronmap.
* @param string $dst Pad naar de doelmap.
@@ -471,7 +471,7 @@ class ContentBackup
*
* Verwijdert eerst alle bestanden en submappen, daarna de map zelf.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Pad naar de te verwijderen map.
* @return void
@@ -507,7 +507,7 @@ class ContentBackup
* suffix, sorteert op wijzigingstijd (oudste eerst) en verwijdert alle
* backups behalve de meest recente.
*
* @since 2.6.4
* @since 2.6.5
*
* @return void
*/
+21 -21
View File
@@ -8,14 +8,14 @@
* bestand en een externe API. Providers vallen terug op de lokale database
* wanneer een lookup geen resultaat oplevert.
*
* @since 2.6.4
* @since 2.6.5
*/
class GeoIP
{
/**
* De analytics-configuratie uit config.json.
*
* @since 2.6.4
* @since 2.6.5
* @var array Bevat o.a. geoip_provider, geoip_mmdb_path en geoip_api_url.
*/
private array $config;
@@ -23,7 +23,7 @@ class GeoIP
/**
* FileCache instantie voor het cachen van API-lookups.
*
* @since 2.6.4
* @since 2.6.5
* @var FileCache|null
*/
private ?FileCache $cache = null;
@@ -31,7 +31,7 @@ class GeoIP
/**
* Initialiseert de GeoIP-provider met de analytics-configuratie.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $analyticsConfig De "analytics" sectie uit config.json. Default lege array.
*/
@@ -49,7 +49,7 @@ class GeoIP
* gereserveerde ranges worden direct afgewezen. MMDB en API vallen
* terug op de lokale database bij een mislukte lookup.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ip IPv4- of IPv6-adres.
* @return string|null Landcode in hoofdletters, of null bij onoplosbare/private adressen.
@@ -91,7 +91,7 @@ class GeoIP
* Geldige codes zijn exact twee letters. De codes ZZ en XX worden
* beschouwd als onbekend en resulteren in null.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string|null $code Ruwe landcode uit een provider.
* @return string|null Genormaliseerde landcode of null indien ongeldig/onbekend.
@@ -112,7 +112,7 @@ class GeoIP
* zoekopdracht uit op basis van het IP-adres. Ondersteunt zowel IPv4
* (10-byte records) als IPv6 (34-byte records).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ip IPv4- of IPv6-adres.
* @return string|null Landcode in hoofdletters of null indien niet gevonden.
@@ -217,7 +217,7 @@ class GeoIP
* het resultaat zeven dagen in een FileCache. De API-URL mag een
* optionele API-key bevatten.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ip IPv4- of IPv6-adres.
* @return string|null Landcode of null indien de lookup faalt.
@@ -256,7 +256,7 @@ class GeoIP
* Opent een MMDB-bestand en extraheert de landcode via de ingebouwde
* MMDBReader. Fouten worden gesilenced en resulteren in null.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ip IPv4- of IPv6-adres.
* @param string $filePath Pad naar het MMDB-bestand.
@@ -276,7 +276,7 @@ class GeoIP
/**
* Zet een 2-letter ISO landcode om naar een regionale vlag-emoji.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string|null $code Landcode of null.
* @return string Vlag-emoji of een wereldbol bij ongeldige invoer.
@@ -301,7 +301,7 @@ class GeoIP
* hun naam in de gevraagde taal. Onbekende codes worden ongewijzigd
* teruggegeven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string|null $code Landcode of null.
* @param string $lang Gewenste taal, 'nl' of 'en'. Default 'nl'.
@@ -364,14 +364,14 @@ class GeoIP
* externe GeoIP2 dependency optioneel is. Ondersteunt 28-bit record sizes
* en de veelvoorkomende datatypes (pointer, string, map, uint, bool).
*
* @since 2.6.4
* @since 2.6.5
*/
class MMDBReader
{
/**
* Pad naar het MMDB-bestand.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private string $file;
@@ -379,7 +379,7 @@ class MMDBReader
/**
* Bestandshandle voor het MMDB-bestand.
*
* @since 2.6.4
* @since 2.6.5
* @var resource|null
*/
private $handle;
@@ -387,7 +387,7 @@ class MMDBReader
/**
* Metadata uit de MMDB-header.
*
* @since 2.6.4
* @since 2.6.5
* @var array Bevat o.a. node_count, record_size en ip_version.
*/
private array $meta;
@@ -395,7 +395,7 @@ class MMDBReader
/**
* Opent het MMDB-bestand en laadt de metadata.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $file Pad naar het MMDB-bestand.
* @throws \InvalidArgumentException Als het bestand niet bestaat.
@@ -414,7 +414,7 @@ class MMDBReader
/**
* Sluit de bestandshandle bij het vernietigen van de instantie.
*
* @since 2.6.4
* @since 2.6.5
*/
public function __destruct()
{
@@ -428,7 +428,7 @@ class MMDBReader
*
* Zoekt naar de MaxMind marker en decodeert de daaropvolgende data.
*
* @since 2.6.4
* @since 2.6.5
*
* @throws \RuntimeException Als de marker niet gevonden wordt.
* @return void
@@ -459,7 +459,7 @@ class MMDBReader
* IP-adres. IPv4-adressen in een IPv6-boom worden correct afgehandeld
* via de ipv4_instance_count metadata.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ip IPv4- of IPv6-adres.
* @return array|null Gedecodeerde datarecord of null indien niet gevonden.
@@ -505,7 +505,7 @@ class MMDBReader
*
* Ondersteunt uitsluitend 28-bit record sizes.
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $node Huidig node-index.
* @param int $bit Bitwaarde (0 voor left, 1 voor right).
@@ -536,7 +536,7 @@ class MMDBReader
* return value bevat de gedecodeerde waarde en de cursorpositie na
* het record.
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $offset Start-offset in het bestand.
* @return array Pair [mixed $value, int $newOffset].
+24 -24
View File
@@ -15,13 +15,13 @@
* "logging.events" configuratiesectie (admin, requests, errors, security,
* content, system).
*
* @since 2.6.4
* @since 2.6.5
*/
class LogManager {
/**
* Event-type voor admin-acties.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const EVENT_ADMIN = 'admin';
@@ -29,7 +29,7 @@ class LogManager {
/**
* Event-type voor request-logging.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const EVENT_REQUESTS = 'requests';
@@ -37,7 +37,7 @@ class LogManager {
/**
* Event-type voor fouten en waarschuwingen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const EVENT_ERRORS = 'errors';
@@ -45,7 +45,7 @@ class LogManager {
/**
* Event-type voor beveiligingsgebeurtenissen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const EVENT_SECURITY = 'security';
@@ -53,7 +53,7 @@ class LogManager {
/**
* Event-type voor content-wijzigingen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const EVENT_CONTENT = 'content';
@@ -61,7 +61,7 @@ class LogManager {
/**
* Event-type voor systeemgebeurtenissen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const EVENT_SYSTEM = 'system';
@@ -69,7 +69,7 @@ class LogManager {
/**
* De "logging" configuratiesectie, of null indien niet geïnitialiseerd.
*
* @since 2.6.4
* @since 2.6.5
* @var array|null
*/
private static $config = null;
@@ -77,7 +77,7 @@ class LogManager {
/**
* Lazy-initialized PDO-verbinding met de SQLite-database, of null.
*
* @since 2.6.4
* @since 2.6.5
* @var \PDO|null
*/
private static $pdo = null;
@@ -85,7 +85,7 @@ class LogManager {
/**
* Pad naar het SQLite-databasebestand, of null indien niet geïnitialiseerd.
*
* @since 2.6.4
* @since 2.6.5
* @var string|null
*/
private static $dbPath = null;
@@ -96,7 +96,7 @@ class LogManager {
* Slaat de configuratie op en stelt het pad naar de SQLite-database in
* onder `admin/storage/logs`.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $loggingConfig De "logging" sectie uit config.json.
* @return void
@@ -110,7 +110,7 @@ class LogManager {
/**
* Geeft aan of logging in het algemeen ingeschakeld is.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien logging ingeschakeld is, anders false.
*/
@@ -125,7 +125,7 @@ class LogManager {
* Controleert eerst of logging in het algemeen ingeschakeld is en
* daarna of het specifieke event aan staat in de configuratie.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $event Een van de EVENT_* constanten.
* @return bool True indien het event geregistreerd moet worden.
@@ -146,7 +146,7 @@ class LogManager {
* Syslog is een aanvullende output en vervangt nooit de lokale
* opslag, en komt dus nooit als driver terug.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string 'sqlite' of 'file'.
*/
@@ -169,7 +169,7 @@ class LogManager {
* geconfigureerd is, wordt de entry tevens naar de remote syslog-server
* gestuurd. Het IP-adres wordt uit de context of de RequestLogger gehaald.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $event Event-type (een EVENT_* constante).
* @param string $level Loglevel (info, warning, error, debug).
@@ -215,7 +215,7 @@ class LogManager {
* Bouwt een syslog-bericht op met facility, severity en ident en stuurt
* dit via een UDP-socket. Verbindings- en schrijffouten worden gesilenced.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $entry De te versturen log-entry.
* @return void
@@ -247,7 +247,7 @@ class LogManager {
* niet beschikbaar is of het schrijven faalt, wordt teruggevallen op
* de file-driver.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $entry De op te slaan log-entry.
* @return void
@@ -284,7 +284,7 @@ class LogManager {
* Zorgt dat de doelmap bestaat en schrijft de entry met een vaste
* opmaak. Schrijffouten worden gesilenced.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $entry De toe te voegen log-entry.
* @return void
@@ -308,7 +308,7 @@ class LogManager {
* fout wordt de interne verbinding op null gezet en null teruggegeven,
* zodat de aanroeper kan terugvallen op de file-driver.
*
* @since 2.6.4
* @since 2.6.5
*
* @return \PDO|null PDO-verbinding of null indien SQLite niet beschikbaar/faalt.
*/
@@ -352,7 +352,7 @@ class LogManager {
/**
* Geeft aan of de SQLite PDO-driver beschikbaar is.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien PDO en de sqlite-driver beschikbaar zijn.
*/
@@ -368,7 +368,7 @@ class LogManager {
* syslog, lpr, news, uucp, cron, authpriv, ftp) en local0 t/m local7.
* Onbekende faciliteiten vallen terug op local0 (16).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $facility Naam van de facility. Default 'local0' wordt door aanroeper gezet.
* @return int Numerieke facility-waarde.
@@ -391,7 +391,7 @@ class LogManager {
* Ondersteunt debug t/m emergency. Onbekende levels vallen terug op
* info (6). De invoer wordt case-insensitive vergeleken.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $level Loglevel (debug, info, notice, warning, error, ...).
* @return int Numerieke severity-waarde (0 t/m 7).
@@ -421,7 +421,7 @@ class LogManager {
* Resultaten worden altijd nieuwste eerst geretourneerd (SQLite via
* ORDER BY id DESC, file via array_reverse).
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $limit Aantal terug te geven entries. Default 200.
* @param string|null $event Optioneel event-filter. Default null (geen filter).
@@ -504,7 +504,7 @@ class LogManager {
* Bij de file-driver wordt het logbestand leeggemaakt. Schrijffouten
* worden gesilenced.
*
* @since 2.6.4
* @since 2.6.5
*
* @return void
*/
+16 -16
View File
@@ -6,14 +6,14 @@
* Logregels worden naar een tekstbestand geschreven en, indien aanwezig,
* tevens door de dynamische LogManager gerouteerd.
*
* @since 2.6.4
* @since 2.6.5
*/
class Logger {
/**
* Loglevel voor debug-boodschappen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const DEBUG = 'DEBUG';
@@ -21,7 +21,7 @@ class Logger {
/**
* Loglevel voor informatieve boodschappen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const INFO = 'INFO';
@@ -29,7 +29,7 @@ class Logger {
/**
* Loglevel voor waarschuwingen.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const WARNING = 'WARNING';
@@ -37,7 +37,7 @@ class Logger {
/**
* Loglevel voor fouten.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
const ERROR = 'ERROR';
@@ -45,7 +45,7 @@ class Logger {
/**
* Pad naar het logbestand, of null indien nog niet geïnitialiseerd.
*
* @since 2.6.4
* @since 2.6.5
* @var string|null
*/
private static $logFile = null;
@@ -53,7 +53,7 @@ class Logger {
/**
* Of debug-logging actief is.
*
* @since 2.6.4
* @since 2.6.5
* @var bool
*/
private static $debugMode = false;
@@ -65,7 +65,7 @@ class Logger {
* map bestaat. Indien geen pad wordt opgegeven valt de logger terug
* op een standaardpad onder de core-map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string|null $logFile Pad naar het logbestand. Default null (standaardlocatie).
* @param bool $debugMode Of debug-logging actief is. Default false.
@@ -89,7 +89,7 @@ class Logger {
/**
* Logt een debug-boodschap (enkel in debug-modus).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $message Boodschap die gelogd moet worden.
* @param array $context Aanvullende contextuele data. Default lege array.
@@ -104,7 +104,7 @@ class Logger {
/**
* Logt een informatieve boodschap.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $message Boodschap die gelogd moet worden.
* @param array $context Aanvullende contextuele data. Default lege array.
@@ -117,7 +117,7 @@ class Logger {
/**
* Logt een waarschuwing.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $message Boodschap die gelogd moet worden.
* @param array $context Aanvullende contextuele data. Default lege array.
@@ -130,7 +130,7 @@ class Logger {
/**
* Logt een fout.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $message Boodschap die gelogd moet worden.
* @param array $context Aanvullende contextuele data. Default lege array.
@@ -149,7 +149,7 @@ class Logger {
* dynamische log gestuurd (errors/warnings naar EVENT_ERRORS, verder
* naar EVENT_SYSTEM).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $level Loglevel (DEBUG, INFO, WARNING, ERROR).
* @param string $message Boodschap die gelogd moet worden.
@@ -180,7 +180,7 @@ class Logger {
/**
* Geeft het pad naar het logbestand.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string|null Pad naar het logbestand of null indien niet geïnitialiseerd.
*/
@@ -191,7 +191,7 @@ class Logger {
/**
* Verwijdert het logbestand.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien het bestand succesvol verwijderd is, anders false.
*/
@@ -209,7 +209,7 @@ class Logger {
* nooit volledig in het geheugen geladen hoeven te worden. De regels
* worden inclusief afsluitende newlines teruggegeven, oudste eerst.
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $lines Aantal terug te halen regels. Default 100.
* @return array<string> Logregels (oudste eerst) of lege array indien niet beschikbaar.
+8 -8
View File
@@ -8,13 +8,13 @@
* buiten het venster en worden genegeerd. De teller wordt opgeslagen in een
* CacheInterface-implementatie, standaard FileCache.
*
* @since 2.6.4
* @since 2.6.5
*/
class RateLimiter {
/**
* Maximum aantal toegestane pogingen binnen het tijdvenster.
*
* @since 2.6.4
* @since 2.6.5
* @var int
*/
private int $maxAttempts;
@@ -22,7 +22,7 @@ class RateLimiter {
/**
* Lengte van het tijdvenster in seconden.
*
* @since 2.6.4
* @since 2.6.5
* @var int
*/
private int $timeWindow;
@@ -30,7 +30,7 @@ class RateLimiter {
/**
* Cache-implementatie waarin de pogingen worden bijgehouden.
*
* @since 2.6.4
* @since 2.6.5
* @var CacheInterface
*/
private CacheInterface $cache;
@@ -38,7 +38,7 @@ class RateLimiter {
/**
* Maak een nieuwe RateLimiter aan.
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $maxAttempts Maximum aantal pogingen binnen het tijdvenster. Default 10.
* @param int $timeWindow Lengte van het tijdvenster in seconden. Default 60.
@@ -57,7 +57,7 @@ class RateLimiter {
* aantal resterende pogingen onder het maximum ligt wordt de huidige
* poging geregistreerd en true teruggegeven; anders false.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $identifier Unieke sleutel voor de te beperken actor (bijv. IP of gebruikersnaam).
* @return bool True wanneer de poging is toegestaan, false wanneer het limiet is bereikt.
@@ -89,7 +89,7 @@ class RateLimiter {
* Telt alleen pogingen die binnen het tijdvenster vallen. Het resultaat
* is nooit negatief.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $identifier Unieke sleutel voor de te beperken actor.
* @return int Aantal resterende pogingen; minimaal 0.
@@ -109,7 +109,7 @@ class RateLimiter {
/**
* Wis alle geregistreerde pogingen voor een identifier.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $identifier Unieke sleutel voor de te beperken actor.
* @return void
+10 -10
View File
@@ -8,14 +8,14 @@
* te matchen, het client-IP te bepalen en bezoekerstype (bot/mens/AI)
* te detecteren.
*
* @since 2.6.4
* @since 2.6.5
*/
class RequestLogger
{
/**
* Pad naar het logbestand.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private string $logFile;
@@ -23,7 +23,7 @@ class RequestLogger
/**
* Maak een nieuwe RequestLogger aan.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $logFile Pad naar het te gebruiken logbestand.
*/
@@ -40,7 +40,7 @@ class RequestLogger
* deze exact twee tekens lang is. De mapstructuur wordt automatisch
* aangemaakt indien deze nog niet bestaat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $page Opgevraagde pagina of route.
* @param string $ip Client IP-adres.
@@ -74,7 +74,7 @@ class RequestLogger
* alleen de eerste vier blokken behouden en de rest vervangen door '::x'.
* Ongeldige adressen worden ongewijzigd teruggegeven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ip Het te anonimiseren IP-adres.
* @return string Het geanonimiseerde IP-adres of het origineel bij een ongeldig adres.
@@ -103,7 +103,7 @@ class RequestLogger
* Bij een prefix-lengte van 0 komt ieder IP van dezelfde adresfamilie overeen.
* Adresfamilies (IPv4 vs IPv6) worden niet onderling gemengd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ip Het te testen client IP-adres.
* @param string[] $list Lijst van IP-adressen en/of CIDR-ranges.
@@ -181,7 +181,7 @@ class RequestLogger
* voorrang aan geldige publieke IP's en slaat interne/reserved ranges
* over; de tweede pass is een fallback voor lokale ontwikkelomgevingen.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Het gedetecteerde client IP-adres, of '127.0.0.1' als fallback.
*/
@@ -242,7 +242,7 @@ class RequestLogger
* ingelogde gebruiker wordt de naam aan het label toegevoegd. Zonder
* BotGuard wordt een algemene bezoeker teruggegeven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $ua De User-Agent string.
* @param string $user Optionele gebruikersnaam; bij 'Gast' of leeg wordt geen naam toegevoegd. Default ''.
@@ -293,7 +293,7 @@ class RequestLogger
* en 'scraper' worden als bot beschouwd en als uppercase string
* teruggegeven; anders null.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string|null Boticategorie ('AI', 'SEARCH' of 'SCRAPER') of null bij geen bot.
*/
@@ -318,7 +318,7 @@ class RequestLogger
* is of een IP/cli-waarde bevat worden als gebruiker 'Gast' gemarkeerd.
* Het resultaat is nieuwste-regel-eerst.
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $lines Aantal te lezen regels vanaf het einde. Default 100.
* @return array<int,array<string,mixed>> Geparseerde logregels, nieuwste eerst. Lege array bij ontbrekend bestand.
+25 -25
View File
@@ -16,13 +16,13 @@ use Twig\Loader\FilesystemLoader;
* fallback naar de default_layout van het thema wanneer de layout
* onbekend is.
*
* @since 2.6.4
* @since 2.6.5
*/
class ThemeManager {
/**
* Volledige CMS-configuratie.
*
* @since 2.6.4
* @since 2.6.5
* @var array Bevat o.a. 'theme_dir' en 'theme'.
*/
private $config;
@@ -30,7 +30,7 @@ class ThemeManager {
/**
* Absoluut pad naar de actieve thema-map.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private $themeDir;
@@ -38,7 +38,7 @@ class ThemeManager {
/**
* Ruwe theme.json configuratie-array.
*
* @since 2.6.4
* @since 2.6.5
* @var array
*/
private $themeConfig;
@@ -46,7 +46,7 @@ class ThemeManager {
/**
* Twig-omgeving voor het renderen van thema-templates.
*
* @since 2.6.4
* @since 2.6.5
* @var Environment
*/
private $twig;
@@ -58,7 +58,7 @@ class ThemeManager {
* De Twig-cache staat uit en auto-escape is uitgeschakeld (de thema's
* beheren eigen escaping waar nodig).
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $config Volledige CMS-configuratie; moet 'theme_dir' en 'theme' bevatten.
*/
@@ -77,7 +77,7 @@ class ThemeManager {
/**
* Geeft het absolute pad van de actieve thema-map.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de thema-map.
*/
@@ -88,7 +88,7 @@ class ThemeManager {
/**
* Geeft de ruwe theme.json configuratie-array.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array Theme.json inhoud, of lege array bij afwezigheid.
*/
@@ -102,7 +102,7 @@ class ThemeManager {
* Leest eerst 'title' uit theme.json, dan 'name', en als laatste
* fallback de mapnaam van het thema.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Thematische titel.
*/
@@ -115,7 +115,7 @@ class ThemeManager {
*
* Bevat o.a. default_template en achtergrondinstellingen.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array Config-sectie, of lege array bij afwezigheid.
*/
@@ -128,7 +128,7 @@ class ThemeManager {
*
* Bevat de mapping van layout-key naar .twig-bestand.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,string> Layout-key => .twig-bestand mapping.
*/
@@ -150,7 +150,7 @@ class ThemeManager {
* 2. Anders fallback naar config.default_template.
* 3. Laatste veiligheidsnet: full_content.twig.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $layout Aangevraagde layout-key (bijv. 'left_sidebar').
* @return string Templacenaam bruikbaar voor de Twig-loader.
@@ -181,7 +181,7 @@ class ThemeManager {
/**
* Geeft de lijst met beschikbare layout-keys uit de "template"-sectie.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string> Lijst met layout-keys.
*/
@@ -192,7 +192,7 @@ class ThemeManager {
/**
* Controleert of een templatebestand bestaat in de thema-map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $file Bestandsnaam van het template (relatief t.o.v. thema-map).
* @return bool True als het bestand bestaat.
@@ -205,7 +205,7 @@ class ThemeManager {
/**
* Rendert een layout-template met de gegeven data.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $layout Aangevraagde layout-key.
* @param array $data Template-variabelen.
@@ -224,7 +224,7 @@ class ThemeManager {
* (0444) gezet om handmatige aanpassingen te voorkomen. Bij een fout
* wordt deze gelogd en null teruggegeven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param bool $force Forceer hercompilatie ongeacht de cache. Default false.
* @return string|null Absoluut pad naar de gecompileerde CSS, of null bij fout/afwezigheid.
@@ -282,7 +282,7 @@ class ThemeManager {
* scssphp). Indien de gecompileerde CSS nog niet bestaat, wordt deze
* alsnog gecompileerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string|null Publieke CSS-URL, of null indien niet beschikbaar.
*/
@@ -304,7 +304,7 @@ class ThemeManager {
/**
* Geeft de publieke URL voor de thema-JS, of null indien niet beschikbaar.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string|null Publieke JS-URL, of null indien niet beschikbaar.
*/
@@ -319,7 +319,7 @@ class ThemeManager {
/**
* Geeft de publieke URL voor een thema-asset.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $assetPath Pad naar de asset binnen de assets/-map van het thema.
* @return string Publieke URL in de vorm '/themes/<naam>/assets/<path>'.
@@ -332,7 +332,7 @@ class ThemeManager {
/**
* Controleert of het thema een SCSS-bronbestand heeft.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True als assets/scss/theme.scss bestaat.
*/
@@ -343,7 +343,7 @@ class ThemeManager {
/**
* Controleert of de gecompileerde CSS nieuwer is dan de SCSS-bron.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True als de CSS-_mtime >= SCSS-mtime, anders false.
*/
@@ -361,7 +361,7 @@ class ThemeManager {
/**
* Controleert of het thema een handmatig CSS-bestand heeft.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True als assets/css/theme.css bestaat.
*/
@@ -374,7 +374,7 @@ class ThemeManager {
*
* De css_compiled-map wordt uitgesloten.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string> Lijst met publieke CSS-URLs.
*/
@@ -399,7 +399,7 @@ class ThemeManager {
/**
* Geeft een lijst met JS-bestanden in de assets/js/-map van het thema.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string> Lijst met publieke JS-URLs.
*/
@@ -424,7 +424,7 @@ class ThemeManager {
/**
* Geeft de URL voor de favicon indien deze bestaat.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string|null Publieke favicon-URL, of null indien niet beschikbaar.
*/
+5 -5
View File
@@ -9,7 +9,7 @@
* returnt de uiteindelijke configuratie-array. Bij falen volgt een
* minimale fallback-configuratie.
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
@@ -23,7 +23,7 @@ $configExamplePath = __DIR__ . '/../../config.json.example';
* Kopieert config.json.example indien aanwezig; anders wordt een ingebouwde
* standaardconfiguratie weggeschreven.
*
* @since 2.6.4
* @since 2.6.5
*/
// Auto-create config.json if it does not exist
if (!file_exists($configJsonPath)) {
@@ -111,7 +111,7 @@ if (!file_exists($configJsonPath)) {
* garandeert de excluded_ips-standaardlijst en converteert relatieve
* content_dir-paden naar absoluut.
*
* @since 2.6.4
* @since 2.6.5
*/
if (file_exists($configJsonPath)) {
$jsonContent = file_get_contents($configJsonPath);
@@ -183,7 +183,7 @@ if (file_exists($configJsonPath)) {
/**
* Actieve theme-configuratie laden vanuit theme.json.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load active theme
$activeTheme = $config['active_theme'] ?? 'default';
@@ -204,7 +204,7 @@ if (file_exists($configJsonPath)) {
/**
* Minimale fallback-configuratie wanneer config.json niet geladen kon worden.
*
* @since 2.6.4
* @since 2.6.5
*/
// Fallback to minimal config
return [
+9 -9
View File
@@ -19,14 +19,14 @@
* 2. Een CodePressCMS-instantie aanmaakt met de config.
* 3. render() aanroept om de pagina uit te voeren.
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
/**
* Configuratie-systeem laden: defaults en config.json-merge.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load configuration system - handles default settings and config.json merging
require_once 'config.php';
@@ -34,7 +34,7 @@ require_once 'config.php';
/**
* Composer-autoloader laden indien aanwezig.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load Composer autoloader
$autoloader = dirname(__DIR__, 2) . '/vendor/autoload.php';
@@ -45,7 +45,7 @@ if (file_exists($autoloader)) {
/**
* Core utility classes laden.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load core utility classes
require_once 'class/Cache.php';
@@ -59,7 +59,7 @@ require_once 'class/ThemeManager.php';
/**
* Logger-klassen laden voor gestructureerde logging met log levels.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load Logger class - structured logging with log levels
require_once 'class/Logger.php';
@@ -68,7 +68,7 @@ require_once 'class/LogManager.php';
/**
* Plugin-systeem laden (interfaces, API's en PluginManager).
*
* @since 2.6.4
* @since 2.6.5
*/
// Load Plugin system
require_once 'plugin/PluginAPIInterface.php';
@@ -79,7 +79,7 @@ require_once 'plugin/PluginManager.php';
/**
* ContentAPI laden: CMS-data-toegang voor PHP content-bestanden.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load ContentAPI class - provides CMS data access for PHP content files
require_once 'class/ContentAPI.php';
@@ -87,7 +87,7 @@ require_once 'class/ContentAPI.php';
/**
* Hoofdclass laden: content parsing, navigation, search en page rendering.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load main CMS class - handles content parsing, navigation, search, and page rendering
require_once 'class/CodePressCMS.php';
@@ -95,7 +95,7 @@ require_once 'class/CodePressCMS.php';
/**
* Logger initialiseren (debug-mode kan via config worden ingeschakeld).
*
* @since 2.6.4
* @since 2.6.5
*/
// Initialize logger (debug mode can be enabled in config)
Logger::init();
+16 -16
View File
@@ -5,14 +5,14 @@
*
* Biedt alleen-lezen toegang tot de site-config (zonder CMS-instance nodig).
*
* @since 2.6.4
* @since 2.6.5
*/
class AdminPluginAPI implements PluginAPIInterface
{
/**
* De site-configuratie als associatieve array.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string,mixed>
*/
private array $config;
@@ -20,7 +20,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Het absolute pad naar de project-root.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private string $projectRoot;
@@ -28,7 +28,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* De actieve admin-taalcode (bijv. 'nl', 'en').
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private string $adminLanguage;
@@ -36,7 +36,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* De admin PluginManager-instantie, optioneel via setPluginManager geïnjecteerd.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginManager|null
*/
private ?PluginManager $pluginManager = null;
@@ -44,7 +44,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Construeer een AdminPluginAPI-instantie met de opgegeven site-config.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array<string,mixed> $siteConfig De site-configuratie.
* @param string $projectRoot Optioneel absoluut pad naar de project-root.
@@ -61,7 +61,7 @@ class AdminPluginAPI implements PluginAPIInterface
* Injecteer de admin PluginManager zodat plugins hun eigen vertalingen
* via dezelfde fallback-keten kunnen resolven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param PluginManager $pm De admin PluginManager-instantie.
* @return void
@@ -74,7 +74,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Haal een configuratiewaarde op via dot-notatie.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Configuratie-sleutel in dot-notatie (bijv. 'language.default').
* @param mixed $default Standaardwaarde indien de sleutel niet bestaat.
@@ -98,7 +98,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Haal de project-rootdirectory op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de project-root.
*/
@@ -113,7 +113,7 @@ class AdminPluginAPI implements PluginAPIInterface
* Relatieve paden uit config.json (bijv. 'content') worden afgezet tegen
* de project-root, conform het gedrag van cms/core/config.php.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de contentdirectory.
*/
@@ -129,7 +129,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Haal het pad naar de pluginsdirectory op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de pluginsdirectory.
*/
@@ -141,7 +141,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Haal de lijst met ingeschakelde plugins op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,string> Lijst met ingeschakelde plugin-namen.
*/
@@ -153,7 +153,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Haal de versie-informatie uit version.php op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,mixed> Versie-informatie met minimaal de sleutel 'version'.
*/
@@ -174,7 +174,7 @@ class AdminPluginAPI implements PluginAPIInterface
*
* System-plugins gebruiken deze om hun vertalingen te resolven.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string De actieve admin-taalcode.
*/
@@ -189,7 +189,7 @@ class AdminPluginAPI implements PluginAPIInterface
* Fallback-keten (afgehandeld door PluginManager):
* aangevraagde taal -> default_language van de plugin -> lege array.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-directorynaam.
* @param string|null $lang Override-taal; standaard de actieve admin-taal.
@@ -207,7 +207,7 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Vertaal een enkele sleutel voor een plugin in de admin-context.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Vertaalsleutel.
* @param string $pluginName Plugin-directorynaam.
+32 -32
View File
@@ -6,14 +6,14 @@
* Biedt toegang tot de CodePressCMS-instance, pagina-informatie, menu, zoekresultaten,
* vertalingen en bestandsoperaties binnen de front-end context.
*
* @since 2.6.4
* @since 2.6.5
*/
class CMSAPI implements PluginAPIInterface
{
/**
* De CodePressCMS-hoofdinstantie.
*
* @since 2.6.4
* @since 2.6.5
* @var CodePressCMS
*/
private CodePressCMS $cms;
@@ -21,7 +21,7 @@ class CMSAPI implements PluginAPIInterface
/**
* De front-end PluginManager-instantie, optioneel via setPluginManager geïnjecteerd.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginManager|null
*/
private ?PluginManager $pluginManager = null;
@@ -29,7 +29,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Construeer een CMSAPI-instantie met de opgegeven CodePressCMS.
*
* @since 2.6.4
* @since 2.6.5
*
* @param CodePressCMS $cms De CodePressCMS-hoofdinstantie.
*/
@@ -42,7 +42,7 @@ class CMSAPI implements PluginAPIInterface
* Injecteer de front-end PluginManager zodat content-plugins hun eigen
* vertalingen via dezelfde fallback-keten kunnen resolven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param PluginManager $pm De front-end PluginManager-instantie.
* @return void
@@ -55,7 +55,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de informatie van de huidige pagina op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,mixed> Pagina-informatie van de huidige pagina.
*/
@@ -67,7 +67,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de titel van de huidige pagina op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string De titel van de huidige pagina, of lege string.
*/
@@ -80,7 +80,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de inhoud van de huidige pagina op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string De HTML-inhoud van de huidige pagina, of lege string.
*/
@@ -93,7 +93,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de URL van de huidige pagina op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string De URL van de huidige pagina inclusief query-parameters.
*/
@@ -107,7 +107,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de menustructuur op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,array<string,mixed>> De menustructuur.
*/
@@ -119,7 +119,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal een configuratiewaarde op via dot-notatie.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Configuratie-sleutel in dot-notatie (bijv. 'language.default').
* @param mixed $default Standaardwaarde indien de sleutel niet bestaat.
@@ -143,7 +143,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de project-rootdirectory op (absoluut, genormaliseerd).
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de project-root.
*/
@@ -158,7 +158,7 @@ class CMSAPI implements PluginAPIInterface
* De CMS-config lost relatieve content_dir-waarden al op
* (zie cms/core/config.php), dus deze wordt as-is teruggegeven.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de contentdirectory.
*/
@@ -170,7 +170,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal het pad naar de pluginsdirectory op (absoluut, genormaliseerd).
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de pluginsdirectory.
*/
@@ -182,7 +182,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de versie-informatie uit version.php op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,mixed> Versie-informatie met minimaal de sleutel 'version'.
*/
@@ -201,7 +201,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal een vertaling op voor de opgegeven sleutel.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Vertaalsleutel.
* @return string De vertaalde string, of $key indien niet gevonden.
@@ -214,7 +214,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de huidige content-taal op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string De huidige taalcode (bijv. 'nl', 'en').
*/
@@ -226,7 +226,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Controleer of de gebruiker zich op de homepage bevindt.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien de huidige pagina de default_page is.
*/
@@ -240,7 +240,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de bestandsinformatie van de huidige pagina op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,mixed>|null Bestandsinformatie of null indien niet aanwezig.
*/
@@ -253,7 +253,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de breadcrumb-HTML op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string De gegenereerde breadcrumb-HTML.
*/
@@ -265,7 +265,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Controleer of de contentdirectory inhoud bevat.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien de contentdirectory niet leeg is.
*/
@@ -277,7 +277,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de zoekresultaten op indien een zoekopdracht actief is.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,array<string,mixed>> De zoekresultaten, of een lege array.
*/
@@ -292,7 +292,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Controleer of momenteel een zoekopdracht wordt uitgevoerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @return bool True indien de search-query-parameter aanwezig is.
*/
@@ -304,7 +304,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de beschikbare talen op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,string> Lijst met beschikbare taalcodes.
*/
@@ -316,7 +316,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Maak een URL voor een pagina.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $page Pagina-identifier.
* @param string|null $lang Taalcode; standaard de huidige content-taal.
@@ -334,7 +334,7 @@ class CMSAPI implements PluginAPIInterface
* Het bestand moet binnen de CMS-directory liggen om willekeurige
* file-inclusion te voorkomen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filePath Absoluut pad naar het PHP-bestand.
* @return string De opgevangen output, of lege string indien ongeldig.
@@ -360,7 +360,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal de inhoud op uit een PHP-, HTML- of Markdown-bestand.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filePath Pad naar het bestand.
* @return string De bestandsinhoud (gerenderd indien PHP/Markdown), of lege string.
@@ -390,7 +390,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Controleer of een bestand in de contentdirectory bestaat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filename Bestandsnaam relatief ten opzichte van de contentdirectory.
* @return bool True indien het bestand bestaat.
@@ -404,7 +404,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Haal alle content-items (mappen + bestanden) op als lijst met entry-arrays.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,array<string,mixed>> Lijst met entries ['path' => ..., 'title' => ..., 'type' => ...].
*/
@@ -418,7 +418,7 @@ class CMSAPI implements PluginAPIInterface
*
* Geeft author_name, author_email en created terug uit de pagina-frontmatter.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,string> Auteursmetadata met sleutels: author_name, author_email, created.
*/
@@ -440,7 +440,7 @@ class CMSAPI implements PluginAPIInterface
* (afgehandeld door PluginManager): aangevraagde taal ->
* default_language van de plugin -> lege array.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-directorynaam.
* @param string|null $lang Override-taal; standaard de huidige content-taal.
@@ -458,7 +458,7 @@ class CMSAPI implements PluginAPIInterface
/**
* Vertaal een enkele sleutel voor een plugin in de front-end context.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Vertaalsleutel.
* @param string $pluginName Plugin-directorynaam.
+8 -8
View File
@@ -5,14 +5,14 @@
*
* Zowel CMSAPI (front-end) als AdminPluginAPI (admin) implementeren deze interface.
*
* @since 2.6.4
* @since 2.6.5
*/
interface PluginAPIInterface
{
/**
* Haal een configuratiewaarde op via dot-notatie.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Configuratie-sleutel in dot-notatie (bijv. 'language.default').
* @param mixed $default Standaardwaarde indien de sleutel niet bestaat.
@@ -23,7 +23,7 @@ interface PluginAPIInterface
/**
* Haal de project-rootdirectory op (absoluut, genormaliseerd).
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de project-root.
*/
@@ -34,7 +34,7 @@ interface PluginAPIInterface
*
* Bij een relatieve configuratiewaarde wordt deze afgezet tegen de project-root.
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de contentdirectory.
*/
@@ -43,7 +43,7 @@ interface PluginAPIInterface
/**
* Haal het pad naar de pluginsdirectory op (absoluut, genormaliseerd).
*
* @since 2.6.4
* @since 2.6.5
*
* @return string Absoluut pad naar de pluginsdirectory.
*/
@@ -54,7 +54,7 @@ interface PluginAPIInterface
*
* Bevat altijd minimaal de sleutel 'version'.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,mixed> Versie-informatie met minimaal de sleutel 'version'.
*/
@@ -67,7 +67,7 @@ interface PluginAPIInterface
* huidige content-taal. De implementatie regelt de fallback naar de
* default_language van de plugin.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-directorynaam.
* @param string|null $lang Optionele override-taal.
@@ -78,7 +78,7 @@ interface PluginAPIInterface
/**
* Vertaal een enkele sleutel voor een plugin in de huidige context.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $key Vertaalsleutel.
* @param string $pluginName Plugin-directorynaam.
+30 -30
View File
@@ -7,14 +7,14 @@
* action- en filter-hooks, en biedt methoden voor plugin-configuratie,
* vertalingen, admin-routes en sidebar-content.
*
* @since 2.6.4
* @since 2.6.5
*/
class PluginManager
{
/**
* Geladen plugin-instanties, geïndexeerd op plugin-naam.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string,object>
*/
private array $plugins = [];
@@ -22,7 +22,7 @@ class PluginManager
/**
* Het absolute pad naar de pluginsdirectory.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private string $pluginsPath;
@@ -30,7 +30,7 @@ class PluginManager
/**
* De geïnjecteerde plugin-API-instantie (CMSAPI of AdminPluginAPI).
*
* @since 2.6.4
* @since 2.6.5
* @var PluginAPIInterface|null
*/
private $api = null;
@@ -38,7 +38,7 @@ class PluginManager
/**
* Lijst met ingeschakelde plugin-namen.
*
* @since 2.6.4
* @since 2.6.5
* @var array<int,string>
*/
private array $enabledPlugins = [];
@@ -46,7 +46,7 @@ class PluginManager
/**
* Geregistreerde action-hooks, gegroepeerd per hook-naam en prioriteit.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string,array<int,array<int,callable>>>
*/
private array $actions = [];
@@ -54,7 +54,7 @@ class PluginManager
/**
* Geregistreerde filter-hooks, gegroepeerd per hook-naam en prioriteit.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string,array<int,array<int,callable>>>
*/
private array $filters = [];
@@ -63,7 +63,7 @@ class PluginManager
* De standaardtaal van de site, gebruikt als fallback voor plugins
* zonder eigen default_language in plugin.json.
*
* @since 2.6.4
* @since 2.6.5
* @var string
*/
private string $siteDefaultLanguage = 'nl';
@@ -71,7 +71,7 @@ class PluginManager
/**
* Construeer een PluginManager en laadt direct de ingeschakelde plugins.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginsPath Absoluut pad naar de pluginsdirectory.
* @param array<int,string> $enabledPlugins Lijst met ingeschakelde plugin-namen.
@@ -91,7 +91,7 @@ class PluginManager
* Wordt gebruikt als fallback wanneer een plugin geen eigen `default_language`
* declareert in plugin.json.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $lang Taalcode (bijv. 'nl', 'en').
* @return void
@@ -106,7 +106,7 @@ class PluginManager
*
* Plugins die een setAPI()-methode implementeren, ontvangen de API-instantie.
*
* @since 2.6.4
* @since 2.6.5
*
* @param PluginAPIInterface $api De plugin-API-instantie.
* @return void
@@ -128,7 +128,7 @@ class PluginManager
* Per plugin wordt het hoofdbestand (<naam>.php) geïncludeerd, de plugin-class
* geïnstantieerd, en action- en filter-hooks automatisch geregistreerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @return void
*/
@@ -179,7 +179,7 @@ class PluginManager
/**
* Registreer een action-callback voor een hook.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $hook Naam van de action-hook.
* @param callable $callback De callback die bij de hook wordt uitgevoerd.
@@ -194,7 +194,7 @@ class PluginManager
/**
* Registreer een filter-callback voor een hook.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $hook Naam van de filter-hook.
* @param callable $callback De callback die de waarde filtert.
@@ -209,7 +209,7 @@ class PluginManager
/**
* Voer alle geregistreerde callbacks voor een action-hook uit.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $hook Naam van de action-hook.
* @param mixed ...$args Argumenten die aan elke callback worden doorgegeven.
@@ -229,7 +229,7 @@ class PluginManager
/**
* Pas alle geregistreerde filter-callbacks toe op een waarde.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $hook Naam van de filter-hook.
* @param mixed $value De initiële waarde die wordt gefilterd.
@@ -251,7 +251,7 @@ class PluginManager
/**
* Haal een specifieke plugin-instantie op.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $name Plugin-naam (directorynaam).
* @return object|null De plugin-instantie of null indien niet geladen.
@@ -264,7 +264,7 @@ class PluginManager
/**
* Haal alle geladen plugin-instanties op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<string,object> Plugin-instanties geïndexeerd op naam.
*/
@@ -276,7 +276,7 @@ class PluginManager
/**
* Haal de lijst met ingeschakelde plugin-namen op.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,string> Lijst met ingeschakelde plugin-namen.
*/
@@ -288,7 +288,7 @@ class PluginManager
/**
* Controleer of een plugin is ingeschakeld.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-naam (directorynaam).
* @return bool True indien de plugin is ingeschakeld.
@@ -304,7 +304,7 @@ class PluginManager
* Standaardwaarden uit plugin.json `settings` worden samengevoegd met
* overrides uit het config.json van de plugin.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-naam (directorynaam).
* @return array<string,mixed> Opgeloste configuratie als [key => value].
@@ -341,7 +341,7 @@ class PluginManager
* 2. CMS site-config `language.default`
* 3. 'nl'
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-directorynaam.
* @return string Taalcode (bijv. 'nl', 'en').
@@ -363,7 +363,7 @@ class PluginManager
*
* Fallback-keten: aangevraagde taal -> standaardtaal van de plugin -> lege array.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-directorynaam.
* @param string $lang Aangevraagde taalcode.
@@ -408,7 +408,7 @@ class PluginManager
* Geeft een associatieve array terug, geïndexeerd op plugin-naam:
* ['Statistics' => [...], 'Logs' => [...], ...]
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $lang Aangevraagde taalcode.
* @param string $context 'admin' of 'site'.
@@ -430,7 +430,7 @@ class PluginManager
*
* Een plugin is viewable tenzij zijn configuratie 'viewable' expliciet op false zet.
*
* @since 2.6.4
* @since 2.6.5
*
* @param object $plugin De plugin-instantie.
* @return bool True indien de plugin viewable is.
@@ -450,7 +450,7 @@ class PluginManager
* Elke plugin met een getSidebarContent()-methode levert HTML die wordt
* ingepakt in een Bootstrap-card met de plugin-titel.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array<int,string>|null $allowedPlugins Optionele whitelist van plugin-namen.
* @return string De samengevoegde sidebar-HTML.
@@ -496,7 +496,7 @@ class PluginManager
/**
* Haal CSS-URL's op van alle ingeschakelde plugins die getCssUrl() implementeren.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,string> Lijst met CSS-URL's.
*/
@@ -519,7 +519,7 @@ class PluginManager
*
* Elke plugin levert [['route' => 'plugin-name/action', 'label' => 'Label', 'icon' => 'bi-icon']].
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,array<string,mixed>> Admin-menu-items van alle plugins.
*/
@@ -545,7 +545,7 @@ class PluginManager
* Plugins implementeren handleAdminRoute(string $action): ?string
* (geeft gerenderde HTML of null terug).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Plugin-naam.
* @param string $action Actie/sub-route binnen de plugin.
@@ -566,7 +566,7 @@ class PluginManager
/**
* Bepaal welke plugin een opgegeven admin-route afhandelt.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $route De admin-route (bijv. 'statistics' of 'statistics/details').
* @return array<string,mixed>|null ['plugin' => naam, 'action' => actie, 'permission' => vereiste permissie] of null.
+7 -7
View File
@@ -7,7 +7,7 @@
* theme- en plugin-assets buiten public/, en routeert /admin en taal-geprefixte
* paden (/nl, /en) door naar admin.php respectievelijk index.php.
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
// Router file for PHP development server - clean URL support + static file serving
@@ -33,7 +33,7 @@ $mimeTypes = [
/**
* Statische bestanden uit public/ serveren met juiste MIME-type.
*
* @since 2.6.4
* @since 2.6.5
*/
// Serve static files from public/
$filePath = $publicDir . $path;
@@ -51,7 +51,7 @@ if (is_file($filePath)) {
*
* Path-traversal wordt afgedwongen via realpath() + prefix-controle.
*
* @since 2.6.4
* @since 2.6.5
*/
// Serve theme assets from the themes/ directory (e.g. /themes/default/js/theme.js)
if (preg_match('#^/themes/([^/]+)/(.+)$#', $path, $m)) {
@@ -78,7 +78,7 @@ if (preg_match('#^/themes/([^/]+)/(.+)$#', $path, $m)) {
*
* Bronmap: admin/theme/default/assets/.
*
* @since 2.6.4
* @since 2.6.5
*/
// Serve admin theme assets (e.g. /admin/assets/css/bootstrap.min.js)
// Served from admin/theme/default/assets/
@@ -103,7 +103,7 @@ if (preg_match('#^/admin/assets/(.+)$#', $path, $m)) {
/**
* Plugin-assets serveren (bijv. /plugins/Navigation/assets/css/navigation.css).
*
* @since 2.6.4
* @since 2.6.5
*/
// Serve plugin assets (e.g. /plugins/Navigation/assets/css/navigation.css)
if (preg_match('#^/plugins/([^/]+)/assets/(.+)$#', $path, $m)) {
@@ -130,7 +130,7 @@ if (preg_match('#^/plugins/([^/]+)/assets/(.+)$#', $path, $m)) {
*
* Default route is 'dashboard' indien geen subpad opgegeven.
*
* @since 2.6.4
* @since 2.6.5
*/
// Admin routes: /admin/login → admin.php?route=login
if (preg_match('#^/admin(?:/(.+))?$#', $path, $m)) {
@@ -145,7 +145,7 @@ if (preg_match('#^/admin(?:/(.+))?$#', $path, $m)) {
* /nl/guide activeert de guide-flag met bestaande ?page=. Default valt
* door naar index.php.
*
* @since 2.6.4
* @since 2.6.5
*/
// Language-prefixed routes: /nl/page/path → index.php?lang=nl&page=page/path
if (preg_match('#^/(nl|en)(?:/(.+))?$#', $path, $m)) {
+190
View File
@@ -0,0 +1,190 @@
# CodePress CMS v2.6.5 — Release Notes
**Release datum:** 2026-08-27
**Codename:** Lyra
**Status:** stable
---
## Samenvatting
Deze release richt zich op **dynamische pad-resolutie**, **volledige
code-documentatie** en een **belangrijke security-fix** rond het standaard
admin-wachtwoord. Daarnaast is de git-geschiedenis schoongemaakt van
kraakbare wachtwoord-hashes die per ongeluk gecommit waren.
---
## Nieuwe features & wijzigingen
### 1. Dynamische pad-resolutie via de Plugin-API
Eerder gaf `AdminPluginAPI::getContentDir()` een relatief pad ("content")
terug zonder dat te normaliseren tegen de project-root. Omdat Apache
`admin.php` uit de `public/` map draait, resolvedde dat relatieve pad naar
`public/content` (niet-bestaand) → het dashboard toonde 0 pagina's, 0
mappen en 0 B aan content.
Nu:
- `PluginAPIInterface` definieert universele pad-methodes
(`getProjectRoot()`, `getContentDir()`, `getPluginsDir()`,
`getVersionInfo()`) die door zowel `CMSAPI` (frontend) als
`AdminPluginAPI` (admin) worden geïmplementeerd.
- `AdminPluginAPI::getContentDir()` normaliseert relatieve paden tegen de
project-root (met Windows-drive-letter detectie), conform
`cms/core/config.php`.
- `CMSAPI` heeft deze methodes erbij gekregen (deze ontbraken op de
frontend-API).
- `public/index.php` media-/assets-serving gebruikt
`$config['content_dir']` i.p.v. een hardcoded `/content` pad, zodat een
aangepaste `content_dir` in `config.json` wordt gevolgd.
- De `Navigation` plugin haalt de content-root via
`$this->api->getContentDir()` i.p.v. hardcoded `dirname(__DIR__, 2)`;
de guide-root via `getProjectRoot()`.
- De `Logs` plugin haalt de log-dir via `$this->api->getProjectRoot()`
i.p.v. hardcoded `dirname(__DIR__, 2)`.
### 2. WordPress-stijl code-documentatie
Alle classes, methods, properties en functies in de codebase zijn
voorzien van volledige docblocks in WordPress-stijl (~450 docblocks):
```
/**
* Summary.
*
* Description.
*
* @since 2.6.5
*
* @param type $var Description.
* @param array $args {
* Optional. An array of arguments.
*
* @type type $key Description. Default 'value'. Accepts 'value', 'value'.
* @type type $key Description.
* }
* @param type $var Description.
* @return type Description.
*/
```
Behandelde bestanden: `AdminAuth`, `Cache`, `RateLimiter`, `RequestLogger`,
`Analytics`, `BotGuard`, `ContentBackup`, `GeoIP`, `Logger`, `LogManager`,
`ThemeManager`, `CodePressCMS`, `PluginAPIInterface`, `CMSAPI`,
`AdminPluginAPI`, `PluginManager`, alle 6 plugins, `public/admin.php`
(82 functies), en de entrypoints/CLI-bestanden.
---
## Security fixes
### 3. Hardcoded plaintext-wachtwoord verwijderd
In `admin/src/AdminAuth.php` stond het standaard-wachtwoord letterlijk in
de broncode:
```php
'password_hash' => password_hash('admin', PASSWORD_BCRYPT),
```
Deze fallback draaide bij een nieuwe installatie wanneer zowel
`admin.json` als `admin.json.example` ontbraken. Het wachtwoord `'admin'`
was hierdoor in de gecommitte broncode zichtbaar.
Nu:
- Bij eerste installatie wordt een **cryptografisch veilig willekeurig
wachtwoord** gegenereerd (`random_bytes`, 16 alfanumerieke tekens).
- De bcrypt-hash wordt weggeschreven naar `admin/config/admin.json`.
- Het plaintext wachtwoord wordt **eenmalig** op het inlogscherm getoond
via een waarschuwing, zodat de beheerder het kan noteren.
- Na de eerste succesvolle login is het wachtwoord nergens meer in
plaintext opgeslagen.
Nieuwe methodes in `AdminAuth`:
- `generateRandomPassword(int $length = 16): string` — CSPRNG-gebaseerd.
- `getGeneratedPassword(): string` — geeft het gegenereerde wachtwoord
terug voor weergave op de login-pagina.
### 4. Git-geschiedenis schoongemaakt
Bij eerdere commits (`d97c67c`, `b8d4a4e`, `5884877`) was
`admin/config/admin.json` per ongeluk gecommit voordat het bestand
gitignored werd. Dit bestand bevatte een bcrypt-hash die kraakt naar het
wachtwoord `'admin'`. Ook `admin/config/admin.json.example` (gecommit)
en het oude `admin-console/config/admin.json` pad bevatten dergelijke
hashes.
Uitgevoerd:
- `git filter-branch` om `admin/config/admin.json`,
`admin/config/admin.json.example` en `admin-console/config/admin.json`
te verwijderen uit **alle commits** op alle branches en tags.
- `reflog expire --expire=now --all` + `gc --prune=now --aggressive` om
oude objecten te verwijderen.
- Verificatie: beide bekende hashes (`nUpoaCNZZ...`, `CV2uORTI...`) en
`password_hash('admin'` komen 0× voor in de hele object-database.
### 5. admin.json.example verwijderd
Het gecommitte `admin/config/admin.json.example` bevatte een geldige
bcrypt-hash (kraakt naar `'admin'`). Omdat de `AdminAuth`-fallback nu
zelf een veilig wachtwoord genereert, is het example-bestand overbodig
geworden en verwijderd uit de repo.
---
## Bijgewerkte documentatie
- `README.md` en `README.en.md`: installatie-stappen herschreven (geen
`admin.json.example` kopie-stap meer; verwijzing naar
`admin`/`admin` inlog verwijderd; uitleg over automatisch gegenereerd
wachtwoord bij eerste installatie).
- `AGENTS.md`: admin-inlog beschrijving bijgewerkt.
- `TODO.md`: v2.6.5 entry toegevoegd.
---
## Onder de motorkap
| Bestand | Wijziging |
|---|---|
| `cms/core/plugin/PluginAPIInterface.php` | Universele pad-methodes toegevoegd |
| `cms/core/plugin/CMSAPI.php` | `getProjectRoot`/`getContentDir`/`getPluginsDir`/`getVersionInfo` toegevoegd |
| `cms/core/plugin/AdminPluginAPI.php` | `getContentDir` normaliseert relatieve paden |
| `public/index.php` | Media-serving via `$config['content_dir']` |
| `plugins/Navigation/Navigation.php` | Content/guide-root via de API |
| `plugins/Logs/Logs.php` | Log-dir via de API |
| `admin/src/AdminAuth.php` | Random-wachtwoord-generator + `getGeneratedPassword` |
| `admin/theme/default/views/login.twig` | Waarschuwing bij eerste installatie |
| `version.php` | 2.6.4 → 2.6.5 |
| `README.md`, `README.en.md`, `AGENTS.md`, `TODO.md` | Docs bijgewerkt |
| ~20 PHP-bestanden | WordPress-stijl docblocks toegevoegd |
---
## Tests uitgevoerd
- `php -l` over alle 67 PHP-bestanden (zonder vendor): 0 syntax-errors.
- Apache smoke-test: login (nieuw wachtwoord), dashboard (4 pagina's /
2 mappen / 282 KB), content, users, plugins, logs, guide, homepage,
pagina en media-serving allen HTTP 200.
- Inloggen met oud wachtwoord `admin` werkt niet meer.
- Eerste-installatie flow getest: bij afwezigheid van `admin.json` wordt
een nieuw wachtwoord gegenereerd en op het inlogscherm getoond.
- Git-historie: beide oude hashes en `password_hash('admin'` 0×
aanwezig in `git log --all -p`.
---
## Upgrade-instructies
1. Pull de nieuwe versie.
2. Als je nog met het standaard-wachtwoord `admin` inlogt: wijzig het
direct na upgrade via de admin-interface of
`php cli/reset-admin-password.php admin <nieuw-wachtwoord>`.
3. optioneel: verwijder `admin/config/admin.json.example` uit je working
tree (is niet meer nodig).
+12 -12
View File
@@ -6,14 +6,14 @@
* Systeem-plugin die een overzichtspagina biedt met site-informatie,
* content-statistieken en een lijst van geïnstalleerde plugins.
*
* @since 2.6.4
* @since 2.6.5
*/
class Dashboard
{
/**
* Plugin-API instantie voor communicatie met de CMS-core.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginAPIInterface|null
*/
private ?PluginAPIInterface $api = null;
@@ -21,7 +21,7 @@ class Dashboard
/**
* Stelt de Plugin-API instantie in.
*
* @since 2.6.4
* @since 2.6.5
* @param PluginAPIInterface $api De Plugin-API instantie.
* @return void
*/
@@ -33,7 +33,7 @@ class Dashboard
/**
* Geeft de plugin-configuratie terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> Plugin-configuratie met title, viewable en type.
*/
public function getConfig(): array
@@ -48,7 +48,7 @@ class Dashboard
/**
* Geeft de admin-menu-items voor deze plugin.
*
* @since 2.6.4
* @since 2.6.5
* @return array<int, array<string, mixed>> Lijst met admin-menu-item configuraties.
*/
public function getAdminMenu(): array
@@ -72,7 +72,7 @@ class Dashboard
* Geeft een HTML-weergave van site-informatie, content-statistieken
* en een plugin-overzicht.
*
* @since 2.6.4
* @since 2.6.5
* @param string $action De uit te voeren actie.
* @return string|null De HTML-uitvoer van het dashboard, of null.
*/
@@ -193,7 +193,7 @@ class Dashboard
/**
* Haalt de site-configuratie op via de AdminPluginAPI.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> De site-configuratie, of een lege array.
*/
private function getSiteConfig(): array
@@ -211,7 +211,7 @@ class Dashboard
/**
* Bepaalt het type (system of content) van een plugin door het hoofdbestand te lezen.
*
* @since 2.6.4
* @since 2.6.5
* @param string $pluginDir Pad naar de plugin-map.
* @param string $pluginName Naam van de plugin.
* @return string Het plugin-type ('system' of 'content').
@@ -235,7 +235,7 @@ class Dashboard
*
* Slaat verborgen en met '-' voorafgegane bestanden en mappen over.
*
* @since 2.6.4
* @since 2.6.5
* @param string $dir Pad naar de map die doorzocht moet worden.
* @param string[] $extensions Optionele lijst van toegestane extensies.
* @return int Het aantal gevonden bestanden.
@@ -269,7 +269,7 @@ class Dashboard
*
* Slaat verborgen en met '-' voorafgegane mappen over.
*
* @since 2.6.4
* @since 2.6.5
* @param string $dir Pad naar de map die doorzocht moet worden.
* @return int Het aantal gevonden submappen.
*/
@@ -294,7 +294,7 @@ class Dashboard
/**
* Berekent de totale bestandsgrootte in bytes van alle bestanden in een map.
*
* @since 2.6.4
* @since 2.6.5
* @param string $dir Pad naar de map die doorzocht moet worden.
* @return int De totale grootte in bytes.
*/
@@ -316,7 +316,7 @@ class Dashboard
/**
* Formateert een byte-grootte naar een leesbare string met eenheid.
*
* @since 2.6.4
* @since 2.6.5
* @param int $bytes Het aantal bytes.
* @return string De geformatteerde grootte met eenheid (bijv. '1.5 MB').
*/
+7 -7
View File
@@ -6,14 +6,14 @@
* Systeem-plugin die een admin-pagina biedt met het IP-adres van de bezoeker
* en het bijbehorende land via de GeoIP-dienst.
*
* @since 2.6.4
* @since 2.6.5
*/
class GeoIPInfo
{
/**
* Plugin-API instantie voor communicatie met de CMS-core.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginAPIInterface|null
*/
private ?PluginAPIInterface $api = null;
@@ -21,7 +21,7 @@ class GeoIPInfo
/**
* Stelt de Plugin-API instantie in.
*
* @since 2.6.4
* @since 2.6.5
* @param PluginAPIInterface $api De Plugin-API instantie.
* @return void
*/
@@ -33,7 +33,7 @@ class GeoIPInfo
/**
* Geeft de plugin-configuratie terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> Plugin-configuratie met title en type.
*/
public function getConfig(): array
@@ -47,7 +47,7 @@ class GeoIPInfo
/**
* Geeft de admin-menu-items voor deze plugin terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<int, array<string, mixed>> Lijst met admin-menu-item configuraties.
*/
public function getAdminMenu(): array
@@ -66,7 +66,7 @@ class GeoIPInfo
/**
* Geeft de admin-routes terug die deze plugin afhandelt.
*
* @since 2.6.4
* @since 2.6.5
* @return array<int, string> Lijst met admin-route namen.
*/
public function getAdminRoutes(): array
@@ -79,7 +79,7 @@ class GeoIPInfo
*
* Bepaalt het IP-adres van de bezoeker en toont het land en de vlag.
*
* @since 2.6.4
* @since 2.6.5
* @param string $route De af te handelen admin-route.
* @return void
*/
+8 -8
View File
@@ -6,14 +6,14 @@
* Content-plugin die informatie over de huidige pagina toont,
* inclusief taal, homepage-status, bestandsinformatie en snelle navigatie.
*
* @since 2.6.4
* @since 2.6.5
*/
class HTMLBlock
{
/**
* Plugin-configuratie.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string, mixed>
*/
private array $config;
@@ -21,7 +21,7 @@ class HTMLBlock
/**
* Plugin-API instantie voor communicatie met de CMS-core.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginAPIInterface|null
*/
private ?PluginAPIInterface $api = null;
@@ -29,7 +29,7 @@ class HTMLBlock
/**
* Initialiseert de plugin met standaardconfiguratie.
*
* @since 2.6.4
* @since 2.6.5
*/
public function __construct()
{
@@ -42,7 +42,7 @@ class HTMLBlock
/**
* Stelt de Plugin-API instantie in.
*
* @since 2.6.4
* @since 2.6.5
* @param PluginAPIInterface $api De Plugin-API instantie.
* @return void
*/
@@ -57,7 +57,7 @@ class HTMLBlock
* Toont informatie over de huidige pagina, taal, homepage-status,
* bestandsinformatie en een snelle navigatielijst.
*
* @since 2.6.4
* @since 2.6.5
* @return string De opgebouwde HTML voor de zijbalk.
*/
public function getSidebarContent(): string
@@ -134,7 +134,7 @@ class HTMLBlock
/**
* Geeft de plugin-configuratie terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> Plugin-configuratie.
*/
public function getConfig(): array
@@ -145,7 +145,7 @@ class HTMLBlock
/**
* Stelt de plugin-configuratie in door deze te mergen met standaardwaarden.
*
* @since 2.6.4
* @since 2.6.5
* @param array<string, mixed> $config De configuratie die samengevoegd moet worden.
* @return void
*/
+7 -7
View File
@@ -6,14 +6,14 @@
* Systeem-plugin die logbestanden uitleest en in een tabel toont,
* met tabbladen voor admin-logs en request-logs.
*
* @since 2.6.4
* @since 2.6.5
*/
class Logs
{
/**
* Plugin-API instantie voor communicatie met de CMS-core.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginAPIInterface|null
*/
private ?PluginAPIInterface $api = null;
@@ -21,7 +21,7 @@ class Logs
/**
* Stelt de Plugin-API instantie in.
*
* @since 2.6.4
* @since 2.6.5
* @param PluginAPIInterface $api De Plugin-API instantie.
* @return void
*/
@@ -33,7 +33,7 @@ class Logs
/**
* Geeft de plugin-configuratie terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> Plugin-configuratie met title, viewable en type.
*/
public function getConfig(): array
@@ -48,7 +48,7 @@ class Logs
/**
* Geeft de admin-menu-items voor deze plugin terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<int, array<string, mixed>> Lijst met admin-menu-item configuraties.
*/
public function getAdminMenu(): array
@@ -75,7 +75,7 @@ class Logs
*
* Leest standaardwaarden uit plugin.json en overschrijft deze met config.json.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> De samengevoegde plugin-configuratie.
*/
private function getPluginConfig(): array
@@ -108,7 +108,7 @@ class Logs
* Leest de geselecteerde log, parset de regels en toont deze in een tabel
* met tabbladen voor admin- en request-logs.
*
* @since 2.6.4
* @since 2.6.5
* @param string $action De uit te voeren actie.
* @return string|null De HTML-uitvoer van de logs-pagina, of null.
*/
+18 -18
View File
@@ -6,14 +6,14 @@
* Content-plugin die de navigatie opbouwt op basis van de mappenstructuur,
* met ondersteuning voor guide-pagina's en reguliere content-pagina's.
*
* @since 2.6.4
* @since 2.6.5
*/
class Navigation
{
/**
* Plugin-configuratie.
*
* @since 2.6.4
* @since 2.6.5
* @var array<string, mixed>
*/
private array $config;
@@ -21,7 +21,7 @@ class Navigation
/**
* Plugin-API instantie voor communicatie met de CMS-core.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginAPIInterface|null
*/
private ?PluginAPIInterface $api = null;
@@ -29,7 +29,7 @@ class Navigation
/**
* Initialiseert de plugin met standaardconfiguratie.
*
* @since 2.6.4
* @since 2.6.5
*/
public function __construct()
{
@@ -43,7 +43,7 @@ class Navigation
/**
* Stelt de Plugin-API instantie in.
*
* @since 2.6.4
* @since 2.6.5
* @param PluginAPIInterface $api De Plugin-API instantie.
* @return void
*/
@@ -55,7 +55,7 @@ class Navigation
/**
* Geeft de plugin-configuratie terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> Plugin-configuratie.
*/
public function getConfig(): array
@@ -66,7 +66,7 @@ class Navigation
/**
* Stelt de plugin-configuratie in door deze te mergen met standaardwaarden.
*
* @since 2.6.4
* @since 2.6.5
* @param array<string, mixed> $config De configuratie die samengevoegd moet worden.
* @return void
*/
@@ -78,7 +78,7 @@ class Navigation
/**
* Geeft het pad naar het CSS-bestand van deze plugin (relatief ten opzichte van de webroot).
*
* @since 2.6.4
* @since 2.6.5
* @return string Het CSS-URL-pad.
*/
public function getCssUrl(): string
@@ -92,7 +92,7 @@ class Navigation
* Detecteert of het om een guide-pagina of een content-pagina gaat en
* bouwt de navigatie dienovereenkomstig op.
*
* @since 2.6.4
* @since 2.6.5
* @return string De HTML-navigatie, of een lege string in admin-context.
*/
public function getSidebarContent(): string
@@ -117,7 +117,7 @@ class Navigation
/**
* Bouwt de navigatie voor de guide-sectie.
*
* @since 2.6.4
* @since 2.6.5
* @param string $lang De huidige taalcode.
* @param string $currentPage De huidige pagina-pad.
* @param bool $isAdmin Of dit in admin-context is.
@@ -141,7 +141,7 @@ class Navigation
/**
* Bouwt de navigatie voor de content-sectie.
*
* @since 2.6.4
* @since 2.6.5
* @param string $lang De huidige taalcode.
* @param string $currentPage De huidige pagina-pad.
* @return string De opgebouwde HTML-navigatie, of een lege string.
@@ -162,7 +162,7 @@ class Navigation
/**
* Bouwt recursief navigatie op vanuit een mapstructuur.
*
* @since 2.6.4
* @since 2.6.5
* @param string $dir Huidige map.
* @param string $relPath Relatief pad vanaf de root.
* @param string $currentPage Huidige pagina-pad.
@@ -257,7 +257,7 @@ class Navigation
/**
* Bouwt de URL voor een pagina-referentie.
*
* @since 2.6.4
* @since 2.6.5
* @param string $pageRef De pagina-referentie.
* @param string $lang De huidige taalcode.
* @param bool $isAdmin Of dit in admin-context is.
@@ -279,7 +279,7 @@ class Navigation
/**
* Controleert of een navigatie-item de huidige pagina is.
*
* @since 2.6.4
* @since 2.6.5
* @param string $pageRef De pagina-referentie van het item.
* @param string $currentPage Het huidige pagina-pad.
* @param string $mode Modus: 'guide' of 'content'.
@@ -297,7 +297,7 @@ class Navigation
/**
* Geeft de beschikbare taalcodes terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<int, string> Lijst met taalcodes.
*/
private function getLanguageCodes(): array
@@ -308,7 +308,7 @@ class Navigation
/**
* Formateert een slug naar een leesbare titel.
*
* @since 2.6.4
* @since 2.6.5
* @param string $slug De te formatteren slug.
* @return string De geformatteerde titel.
*/
@@ -324,7 +324,7 @@ class Navigation
*
* Valt terug op formatTitle() wanneer geen H1 gevonden is.
*
* @since 2.6.4
* @since 2.6.5
* @param string $filePath Pad naar het bestand.
* @return string De gevonden titel, of een lege string.
*/
@@ -347,7 +347,7 @@ class Navigation
/**
* Rendert de navigatie-items als HTML.
*
* @since 2.6.4
* @since 2.6.5
* @param array $items Navigatie-items.
* @param int $depth Nesting-diepte (0 = topniveau). Standaard 0.
* @return string De gegenereerde HTML.
+8 -8
View File
@@ -6,14 +6,14 @@
* Systeem-plugin die analytics-gegevens toont, zoals totaal aantal views,
* unieke bezoekers, landen en top-pagina's.
*
* @since 2.6.4
* @since 2.6.5
*/
class Statistics
{
/**
* Plugin-API instantie voor communicatie met de CMS-core.
*
* @since 2.6.4
* @since 2.6.5
* @var PluginAPIInterface|null
*/
private ?PluginAPIInterface $api = null;
@@ -21,7 +21,7 @@ class Statistics
/**
* Stelt de Plugin-API instantie in.
*
* @since 2.6.4
* @since 2.6.5
* @param PluginAPIInterface $api De Plugin-API instantie.
* @return void
*/
@@ -33,7 +33,7 @@ class Statistics
/**
* Geeft de plugin-configuratie terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> Plugin-configuratie met title, viewable en type.
*/
public function getConfig(): array
@@ -48,7 +48,7 @@ class Statistics
/**
* Geeft de admin-menu-items voor deze plugin terug.
*
* @since 2.6.4
* @since 2.6.5
* @return array<int, array<string, mixed>> Lijst met admin-menu-item configuraties.
*/
public function getAdminMenu(): array
@@ -75,7 +75,7 @@ class Statistics
*
* Leest standaardwaarden uit plugin.json en overschrijft deze met config.json.
*
* @since 2.6.4
* @since 2.6.5
* @return array<string, mixed> De samengevoegde plugin-configuratie.
*/
private function getPluginConfig(): array
@@ -108,7 +108,7 @@ class Statistics
* Toont analytics-gegevens zoals views, unieke bezoekers, landen en
* top-pagina's, mits analytics ingeschakeld is.
*
* @since 2.6.4
* @since 2.6.5
* @param string $action De uit te voeren actie.
* @return string|null De HTML-uitvoer van de statistieken-pagina, of null.
*/
@@ -233,7 +233,7 @@ class Statistics
/**
* Haalt de Analytics-instantie op basis van de analytics-configuratie.
*
* @since 2.6.4
* @since 2.6.5
* @return Analytics|null De Analytics-instantie, of null als analytics uitgeschakeld is.
*/
private function getAnalytics(): ?Analytics
+82 -82
View File
@@ -79,7 +79,7 @@ $twig->addFunction(new \Twig\TwigFunction('role_label', function($role) {
* taalbestand niet bestaat of geen array teruggeeft, valt de functie terug
* op de Nederlandse vertalingen.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array|null $siteConfig Site-configuratie array met admin_language en language.default.
* @return array<string,string> Vertaal-string map (key => vertaling). Leeg indien geen bestand gevonden.
@@ -155,7 +155,7 @@ $route = $_GET['route'] ?? '';
* van dat thema naar een `header_color`. Wanneer het thema of de kleur
* ontbreekt, wordt de standaardkleur `#0a369d` teruggegeven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $config App-configuratie array met de sleutel `config_json`.
* @return string CSS-kleurwaarde (bijv. '#0a369d').
@@ -177,7 +177,7 @@ function getSidebarColor($config) {
/**
* Geeft de lijst van beschermde plugins die niet uitgeschakeld of verwijderd mogen worden.
*
* @since 2.6.4
* @since 2.6.5
*
* @return array<int,string> Namen van beschermde plugins (bijv. ['Navigation']).
*/
@@ -189,7 +189,7 @@ function getProtectedPlugins(): array {
/**
* Controleert of een pluginnaam op de lijst van beschermde plugins staat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginName Naam van de plugin om te controleren.
* @return bool True wanneer de plugin beschermd is, anders false.
@@ -210,7 +210,7 @@ function isProtectedPlugin(string $pluginName): bool {
* 2. plugin.json 'type' override
* 3. regex uit <Plugin>.php 'type' => '...' (fallback als plugin.json geen type bevat)
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginsDir Absoluut pad naar de plugins-directory.
* @return array<int,array{name:string,title:string,type:string}> Uitsluitend content-type plugins.
@@ -602,7 +602,7 @@ switch ($route) {
* Toont o.a. het aantal pagina's, mappen, content-grootte, PHP/CMS-versie
* en een overzicht van alle plugins met hun ingeschakelde status.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, plugins_dir, config_json).
@@ -672,7 +672,7 @@ function handleDashboard($auth, $config, $twig, $user, $csrf, $siteConfig): void
* hoe de interface eruitziet met die rol. Verwacht een geldige CSRF-token
* en een `new_role` POST-veld; stuur daarna door naar het dashboard.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (voor logging).
@@ -705,7 +705,7 @@ function handleRoleSwitch($auth, $config): void
* override ongedaan maken en terugkeren naar de echte rol. Verwacht een
* geldige CSRF-token en stuurt daarna door naar het dashboard.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (voor logging).
@@ -738,7 +738,7 @@ function handleRoleReset($auth, $config): void
* ondersteuning voor uploaden van bestanden (POST). Bevat path-traversal
* bescherming via str_replace en trim.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -838,7 +838,7 @@ function handleContent($auth, $config, $twig, $user, $csrf, $siteConfig): void
* bestandsnamen (content gebruikt taal-prefix in bestandsnamen, anders dan
* plugins/themes).
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, plugins_dir).
@@ -1303,7 +1303,7 @@ function handleContentFiles($auth, $config, $twig, $user, $csrf, $siteConfig): v
* afbeeldingen, video, audio, pdf, zip, office-docs, css, scss, js, json, html, md.
* Bevat path-traversal bescherming via realpath + prefix-check op content_dir.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -1408,7 +1408,7 @@ function handleContentFileUpload($auth, $config, $user): void
* Weigert mappen, dotfiles en paden die buiten content_dir vallen. Na
* verwijdering wordt terugverwezen naar de map waar het bestand in stond.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -1480,7 +1480,7 @@ function handleContentFileDelete($auth, $config, $user): void
* (GET) met een dropdown van beschikbare mappen en voert de hernoemactie (move)
* uit op POST. Optioneel kan de bestandsnaam worden gewijzigd (extensie behouden).
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -1620,7 +1620,7 @@ function handleContentFileMove($auth, $config, $twig, $user, $csrf): void
* Variant van handleContentDirCreate die terugverwijst naar content-files
* (de verenigde content-editor). Alleen POST met een geldige CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -1676,7 +1676,7 @@ function handleContentDirCreateIn($auth, $config, $user): void
* Variant van handleContentDirRename die terugverwijst naar content-files.
* Toont een hernoem-formulier (GET) en voert de hernoemactie uit op POST.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -1768,7 +1768,7 @@ function handleContentDirRenameIn($auth, $config, $twig, $user, $csrf): void
* Alleen lege mappen mogen verwijderd worden (verborgen .bak bestanden worden
* genegeerd bij de leegte-check). Alleen POST met een geldige CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -1840,7 +1840,7 @@ function handleContentDirDeleteIn($auth, $config, $user): void
* op (POST). Frontmatter (layout/plugins/edited) wordt bijgewerkt bij opslaan.
* Bevat path-traversal bescherming via realpath + prefix-check.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, plugins_dir).
@@ -1985,7 +1985,7 @@ function handleContentEdit($auth, $config, $twig, $user, $csrf, $siteConfig): vo
* (layout/created/edited) en een stub, waarna wordt doorverwezen naar de
* content-editor.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -2088,7 +2088,7 @@ function handleContentNew($auth, $config, $twig, $user, $csrf, $siteConfig): voi
* Verwacht een geldige CSRF-token en een `file` POST/GET-veld. Na verwijderen
* wordt doorverwezen naar de map waar het bestand in stond.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -2128,7 +2128,7 @@ function handleContentDelete($auth, $config): void
* CSRF-token en een `dirname` POST-veld. Na aanmaken wordt terugverwezen
* naar de content-lijst.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -2171,7 +2171,7 @@ function handleContentDirCreate($auth, $config): void
* Toont een hernoem-formulier (GET) en voert de hernoemactie uit op POST.
* Na succesvolle hernoeming wordt doorverwezen naar de hernoemde map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -2235,7 +2235,7 @@ function handleContentDirRename($auth, $config, $twig, $user, $csrf): void
* Verwacht een geldige CSRF-token en verwijdert de map alleen als deze
* leeg is. Na verwijderen wordt terugverwezen naar de bovenliggende map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -2279,7 +2279,7 @@ function handleContentDirDelete($auth, $config): void
* doelmappen en voert de verplaatsactie uit op POST. Na succes wordt
* doorverwezen naar de doelmap.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -2370,7 +2370,7 @@ function handleContentMove($auth, $config, $twig, $user, $csrf): void
* Op POST met actie `download_zip` wordt een ZIP-backup van content gemaakt
* en direct als download aangeboden.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, codepress_root).
@@ -2452,7 +2452,7 @@ function handleContentBackup($auth, $config, $twig, $user, $csrf): void
* ContentBackup::restoreFromZip aan en stuurt daarna door naar de
* backup-pagina met een statusmelding.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, codepress_root).
@@ -2499,7 +2499,7 @@ function handleContentRestore($auth, $config): void
* Verwacht een geldige CSRF-token en roept ContentBackup::gitInit aan.
* Na afloop wordt doorverwezen naar de backup-pagina met een statusmelding.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, codepress_root).
@@ -2536,7 +2536,7 @@ function handleContentGitInit($auth, $config): void
* Verwacht een geldige CSRF-token en een `commit_message` POST-veld. Roept
* ContentBackup::gitCommit aan en stuurt daarna door naar de backup-pagina.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, codepress_root).
@@ -2574,7 +2574,7 @@ function handleContentGitCommit($auth, $config): void
* Verwacht een geldige CSRF-token en een `commit` POST-veld met de commit-hash.
* Roept ContentBackup::gitRestore aan en stuurt daarna door naar de backup-pagina.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, codepress_root).
@@ -2612,7 +2612,7 @@ function handleContentGitRestore($auth, $config): void
* in config.json. Op succes wordt via PRG doorgestuurd zodat de nieuwe
* admin-taal direct wordt toegepast.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (config_json, content_dir).
@@ -2689,7 +2689,7 @@ function handleConfig($auth, $config, $twig, $user, $csrf): void
* admin-config JSON. Op POST (met geldige CSRF-token) worden de waarden
* opgeslagen en bevestigd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (admin_config).
@@ -2742,7 +2742,7 @@ function handleSecurity($auth, $config, $twig, $user, $csrf): void
* Toont per thema de naam, of deze actief/beschermd is, SCSS-compile status
* en -mtimes. Actieve thema's worden eerst getoond, daarna alfabetisch.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -2819,7 +2819,7 @@ function handleTheme($auth, $config, $twig, $user, $csrf, $siteConfig): void
* op een bestaand thema (kopiëren) of met een lege uniforme structuur. Op
* succes wordt doorverwezen naar de thema-editor.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -2908,7 +2908,7 @@ function handleThemeNew($auth, $config, $twig, $user, $csrf): void
/**
* Maakt een uniforme thema-structuur aan (theme.json, layouts, partials, assets/scss, etc.).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $themeDir Absoluut pad naar de nieuwe thema-map (al aangemaakt).
* @param string $themeName Opgeschoonde thema-naam.
@@ -2965,7 +2965,7 @@ function createUniformThemeStructure(string $themeDir, string $themeName): void
*
* Slaat css_compiled/ (runtime-artefact) en .git/.gitkeep over.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $src Bron-directory (absoluut).
* @param string $dst Doel-directory (absoluut, bestaat al).
@@ -3000,7 +3000,7 @@ function copyDirRecursive(string $src, string $dst): void
/**
* Verwijdert een directory recursief (gebruikt door theme-delete).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Te verwijderen directory (absoluut).
* @return void
@@ -3030,7 +3030,7 @@ function removeDirRecursive(string $dir): void
* via realpath + prefix-check. Het default-thema kan wel bewerkt worden (geen
* protected block), maar verwijderen/activeren is geblokkeerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -3277,7 +3277,7 @@ function handleThemeEdit($auth, $config, $twig, $user, $csrf): void
* audio, pdf, css, scss, js, json, html, md, twig, fonts. Bevat path-traversal
* bescherming via realpath + prefix-check op de thema assets-map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -3387,7 +3387,7 @@ function handleThemeFileUpload($auth, $config, $user): void
* Weigert mappen, dotfiles, theme.json en paden die buiten de thema-map
* vallen. Na verwijderen wordt terugverwezen naar theme.json in de editor.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -3468,7 +3468,7 @@ function handleThemeFileDelete($auth, $config, $user): void
* dropdown van beschikbare mappen en voert de hernoemactie (move) uit op POST.
* theme.json kan niet verplaatst worden.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -3601,7 +3601,7 @@ function handleThemeFileMove($auth, $config, $twig, $user, $csrf): void
* Verwacht een geldige CSRF-token en een `theme` POST-veld. Het thema moet
* bestaan. Na activeren wordt terugverwezen naar het thema-overzicht.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (config_json).
@@ -3647,7 +3647,7 @@ function handleThemeActivate($auth, $config, $user): void
* Alleen niet-actieve, niet-default thema's mogen verwijderd worden. Na
* verwijderen wordt terugverwezen naar het thema-overzicht met een melding.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (config_json).
@@ -3700,7 +3700,7 @@ function handleThemeDelete($auth, $config, $user): void
* Verwacht een geldige CSRF-token en een `theme` POST-veld. Na compilatie
* wordt terugverwezen naar het thema-overzicht met een statusmelding.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -3772,7 +3772,7 @@ function handleThemeScss($auth, $config, $user): void
* type (content/system). Plugin-type wordt bepaald uit plugin.json of de
* plugin PHP-bron.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir, config_json).
@@ -3837,7 +3837,7 @@ function handlePlugins($auth, $config, $twig, $user, $csrf): void
* plugin.json en een PHP-stub. Op succes wordt doorverwezen naar de
* plugin-editor.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -3905,7 +3905,7 @@ function handlePluginsNew($auth, $config, $twig, $user, $csrf): void
* map aanmaken. Beschermde plugins kunnen niet bewerkt worden. Bevat
* path-traversal bescherming via realpath + prefix-check.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -4163,7 +4163,7 @@ function handlePluginsEdit($auth, $config, $twig, $user, $csrf): void
* doelmap moet binnen de echte plugin assets-map liggen. Beschermde plugins
* worden geblokkeerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -4268,7 +4268,7 @@ function handlePluginsFileUpload($auth, $config, $user): void
* verwijderen wordt terugverwezen naar het hoofdpluginbestand. Beschermde
* plugins worden geblokkeerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -4349,7 +4349,7 @@ function handlePluginsFileDelete($auth, $config, $user): void
* bron en doel moeten beide binnen de echte plugin-map vallen. Beschermde
* plugins worden geblokkeerd.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -4484,7 +4484,7 @@ function handlePluginsFileMove($auth, $config, $twig, $user, $csrf): void
* Spiegelt handleContentDirCreateIn. Alleen POST met een geldige CSRF-token.
* Na aanmaken wordt doorverwezen naar de nieuwe map in de thema-editor.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -4548,7 +4548,7 @@ function handleThemeDirCreateIn($auth, $config, $user): void
* voert de hernoemactie uit op POST. Na succes wordt doorverwezen naar de
* hernoemde map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -4645,7 +4645,7 @@ function handleThemeDirRenameIn($auth, $config, $twig, $user, $csrf): void
* Spiegelt handleContentDirDeleteIn. Alleen lege mappen mogen verwijderd
* worden. Alleen POST met een geldige CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -4718,7 +4718,7 @@ function handleThemeDirDeleteIn($auth, $config, $user): void
* Alleen POST met een geldige CSRF-token. Na aanmaken wordt doorverwezen naar
* de nieuwe map in de plugin-editor.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -4782,7 +4782,7 @@ function handlePluginsDirCreateIn($auth, $config, $user): void
* Toont een hernoem-formulier (GET) en voert de hernoemactie uit op POST. Na
* succes wordt doorverwezen naar de hernoemde map.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -4880,7 +4880,7 @@ function handlePluginsDirRenameIn($auth, $config, $twig, $user, $csrf): void
* worden. Beschermde plugins worden geblokkeerd. Alleen POST met een geldige
* CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -4952,7 +4952,7 @@ function handlePluginsDirDeleteIn($auth, $config, $user): void
* Accepteert: scope (content|theme|plugin), source (relatief pad) en
* destination (relatieve map). Retourneert JSON: {ok, message, newPath?, redirect?}.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, plugins_dir).
@@ -5068,7 +5068,7 @@ function handleTreeMove($auth, $config, $user): void
* config.json van de plugin. Op POST worden de waarden opgeslagen. Setting-
* labels/helpteksten worden via plugin-vertalingen opgelost.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir, config_json).
@@ -5195,7 +5195,7 @@ function handlePluginsConfig($auth, $config, $twig, $user, $csrf): void
* Beschermde plugins kunnen niet uitgeschakeld worden. Verwacht een geldige
* CSRF-token en een `plugin` POST-veld.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (config_json).
@@ -5250,7 +5250,7 @@ function handlePluginsToggle($auth, $config): void
* CSRF-token en een `plugin` POST-veld. Na verwijderen wordt terugverwezen
* naar het plugin-overzicht.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (plugins_dir).
@@ -5310,7 +5310,7 @@ function handlePluginsDelete($auth, $config): void
* Toont alle gebruikers met zoek- en rolfilters. Op POST kan een gebruiker
* verwijderd of van rol gewisseld worden. Verwacht een geldige CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -5394,7 +5394,7 @@ function handleUsers($auth, $config, $twig, $user, $csrf): void
* wachtwoord-wijziging (alleen als de echte rol admin is) en verwijderen.
* Een gebruiker kan zichzelf niet verwijderen. Verwacht een geldige CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -5495,7 +5495,7 @@ function handleUsersEdit($auth, $config, $twig, $user, $csrf): void
* wachtwoord, rol, email en auteur-gegevens. Op succes wordt doorverwezen
* naar de gebruiker-bewerkpagina. Verwacht een geldige CSRF-token.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -5553,7 +5553,7 @@ function handleUsersNew($auth, $config, $twig, $user, $csrf): void
* navigatie-zijbalk (via de Navigation plugin). Valt terug op Engels indien
* de gevraagde taal niet bestaat.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -5662,7 +5662,7 @@ function handleGuide($auth, $config, $twig, $user, $csrf): void
* Leest de huidige versie uit version.php en controleert of de .git-map
* schrijfbaar is voor eventuele updates.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array.
@@ -5699,7 +5699,7 @@ function handleUpdate($auth, $config, $twig, $user, $csrf): void
* Toont een lijst van bestanden en mappen in de opgegeven subdir. Bevat
* path-traversal bescherming via str_replace.
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir).
@@ -5745,7 +5745,7 @@ function handleMedia($auth, $config, $twig, $user, $csrf): void
* Path-traversal bescherming: elk opgelost pad moet beginnen met de opgeloste
* basismap (content-, plugin-assets- of theme-assets-map).
*
* @since 2.6.4
* @since 2.6.5
*
* @param AdminAuth $auth Authenticatie-object.
* @param array $config App-configuratie array (content_dir, plugins_dir).
@@ -5834,7 +5834,7 @@ function handleMediaList($auth, $config): void
/**
* Schrijft een admin-logregel naar het logbestand en (indien beschikbaar) LogManager.
*
* @since 2.6.4
* @since 2.6.5
*
* @param array $config App-configuratie array met de sleutel `log_file`.
* @param string $level Logniveau (bijv. 'info', 'warning', 'error').
@@ -5860,7 +5860,7 @@ function adminLog(array $config, string $level, string $message): void
/**
* Telt recursief het aantal bestanden in een directory, optioneel gefilterd op extensies.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Te scannen directory (absoluut).
* @param string[] $extensions Toegestane extensies (zonder punt). Leeg = alle bestanden.
@@ -5887,7 +5887,7 @@ function countFiles(string $dir, array $extensions = []): int
/**
* Telt recursief het aantal mappen in een directory, exclusief dotfiles.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Te scannen directory (absoluut).
* @return int Aantal gevonden mappen. 0 wanneer de dir niet bestaat.
@@ -5912,7 +5912,7 @@ function countDirs(string $dir): int
/**
* Telt het aantal ingeschakelde plugins in de site-config.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginsDir Plugins-directory (ongebruikt, voor compatibiliteit).
* @param string $configJson Pad naar config.json.
@@ -5928,7 +5928,7 @@ function countEnabledPlugins(string $pluginsDir, string $configJson): int
/**
* Berekent recursief de totale bestandsgrootte (in bytes) van een directory.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Te scannen directory (absoluut).
* @return int Totale grootte in bytes. 0 wanneer de dir niet bestaat.
@@ -5952,7 +5952,7 @@ function dirSize(string $dir): int
/**
* Formatteert een byte-grootte naar een leesbare string (B/KB/MB/GB/TB).
*
* @since 2.6.4
* @since 2.6.5
*
* @param int $bytes Aantal bytes.
* @return string Geformatteerde grootte met eenheid (bijv. '1.5 MB').
@@ -5974,7 +5974,7 @@ function formatSize(int $bytes): string
* Toont per item de naam, pad, of het een map is, extensie, grootte en
* wijzigingsdatum. Mappen worden eerst getoond, daarna bestanden alfabetisch.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $fullPath Absoluut pad van de te scannen map.
* @param string $subdir Relatieve subdir binnen content (voor pad-berekening).
@@ -6035,7 +6035,7 @@ function scanContentDir(string $fullPath, string $subdir): array
* wordt gebruikt; de echte basismap is het anker en elk opgelost kindpad wordt
* gecontroleerd om daarbinnen te blijven.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $dir Absoluut pad naar de te scannen directory.
* @param string $scope Een van: 'plugin', 'theme', 'content'. Default 'plugin'.
@@ -6058,7 +6058,7 @@ function scanEditorFiles(string $dir, string $scope = 'plugin'): array
/**
* Recursieve helper voor scanEditorFiles(). Bouwt één niveau van de boom.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $absDir Absoluut pad van de te scannen directory.
* @param string $relPath Relatief pad van $absDir binnen de basis (leeg voor root).
@@ -6144,7 +6144,7 @@ function scanEditorFilesNode(string $absDir, string $relPath, string $realBase,
/**
* Scant de bestandsboom van een plugin-directory.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $pluginDir Absoluut pad naar de plugin-directory.
* @return array<int,array<string,mixed>> Geneste bestandsboom.
@@ -6157,7 +6157,7 @@ function scanPluginFiles(string $pluginDir): array
/**
* Scant de bestandsboom van een thema-directory.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $themeDir Absoluut pad naar de thema-directory.
* @return array<int,array<string,mixed>> Geneste bestandsboom.
@@ -6170,7 +6170,7 @@ function scanThemeFiles(string $themeDir): array
/**
* Scant de bestandsboom van een content-directory.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $contentDir Absoluut pad naar de content-directory.
* @return array<int,array<string,mixed>> Geneste bestandsboom.
@@ -6187,7 +6187,7 @@ function scanContentFiles(string $contentDir): array
* sleutel. Mappen worden meegenomen als ze content bevatten (vertegenwoordigd
* door hun pad).
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $contentDir Absoluut pad naar de content-directory.
* @return array<string,string> Gesorteerde lijst van [pageKey => displayLabel].
@@ -6262,7 +6262,7 @@ function collectContentPages(string $contentDir): array
/**
* Werkt een frontmatter-sleutel bij in content of voegt deze toe.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Content met optionele --- frontmatter.
* @param string $key Frontmatter-sleutel om bij te werken.
@@ -6298,7 +6298,7 @@ function updateContentFrontmatter(string $content, string $key, string $value):
/**
* Leest een enkele waarde uit de frontmatter van content.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $content Content met optionele --- frontmatter.
* @param string $key Frontmatter-sleutel om te lezen.
@@ -6318,7 +6318,7 @@ function extractFrontmatterValue(string $content, string $key): string
/**
* Bepaalt de taal-prefix van een bestandsnaam (bijv. 'nl' voor 'nl.test.md').
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $file Bestandsnaam of -pad.
* @return string Taalcode ('nl', 'en', 'de', 'fr', 'es') of 'nl' als standaard.
@@ -6338,7 +6338,7 @@ function extractLanguagePrefix(string $file): string
*
* Kopieert het bestand naar <dirname>/.bak/<basename>.<timestamp>.
*
* @since 2.6.4
* @since 2.6.5
*
* @param string $filePath Absoluut pad naar het te backuppen bestand.
* @return void
+5 -5
View File
@@ -8,7 +8,7 @@
* /plugins/ URLs naar dit bestand. Paden worden via realpath() + prefix-
* check afgedwongen binnen de juiste asset-map om path traversal te voorkomen.
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
/**
@@ -40,7 +40,7 @@ $assetFile = null;
/**
* /themes/<naam>/assets/...: theme-asset matchen en pad oplossen.
*
* @since 2.6.4
* @since 2.6.5
*/
// /themes/<name>/assets/...
if (preg_match('#^/themes/([^/]+)/assets/(.+)$#', $path, $m)) {
@@ -52,7 +52,7 @@ if (preg_match('#^/themes/([^/]+)/assets/(.+)$#', $path, $m)) {
/**
* /admin/assets/...: admin-theme-asset matchen (default admin theme).
*
* @since 2.6.4
* @since 2.6.5
*/
// /admin/assets/...
elseif (preg_match('#^/admin/assets/(.+)$#', $path, $m)) {
@@ -63,7 +63,7 @@ elseif (preg_match('#^/admin/assets/(.+)$#', $path, $m)) {
/**
* /plugins/<naam>/assets/...: plugin-asset matchen en pad oplossen.
*
* @since 2.6.4
* @since 2.6.5
*/
// /plugins/<name>/assets/...
elseif (preg_match('#^/plugins/([^/]+)/assets/(.+)$#', $path, $m)) {
@@ -79,7 +79,7 @@ elseif (preg_match('#^/plugins/([^/]+)/assets/(.+)$#', $path, $m)) {
* Controleert dat het opgeloste pad binnen de asset-map blijft en een
* regulier bestand is; anders volgt een 404.
*
* @since 2.6.4
* @since 2.6.5
*/
if ($assetFile && $realBase) {
$realFile = realpath($assetFile);
+13 -13
View File
@@ -8,7 +8,7 @@
* controles uit, registreert analytics- en logvermeldingen en render
* uiteindelijk de pagina via CodePressCMS::render().
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
require_once __DIR__ . '/../cms/core/index.php';
@@ -18,7 +18,7 @@ $config = include __DIR__ . '/../cms/core/config.php';
/**
* Log-systeem initialiseren op basis van de logging-configuratie.
*
* @since 2.6.4
* @since 2.6.5
*/
// Initialize dynamic logging
LogManager::init($config['logging'] ?? []);
@@ -26,7 +26,7 @@ LogManager::init($config['logging'] ?? []);
/**
* Security headers instellen voor alle front-end responses.
*
* @since 2.6.4
* @since 2.6.5
*/
// Security headers
header('X-Content-Type-Options: nosniff');
@@ -43,7 +43,7 @@ header_remove('X-Powered-By');
* content-map dynamisch op basis van config['content_dir'] en serveert
* bestanden buiten public/ met een pad-controle om traversal te blokkeren.
*
* @since 2.6.4
* @since 2.6.5
*/
// Serve media files from any content/ subdirectory via /-media/
// Serve files from content/-assets/ via /-assets/ (backward compatible)
@@ -88,7 +88,7 @@ if (strpos($path, '/-media/') === 0) {
* /-assets/ route: serveert bestanden uit content/-assets/ of de content-
* root, met backward-compatibiliteit en path-traversal-controle.
*
* @since 2.6.4
* @since 2.6.5
*/
if (strpos($path, '/-assets/') === 0) {
$relative = ltrim(substr($path, 8), '/');
@@ -136,7 +136,7 @@ if ($path === '/robots.txt') {
*
* Voorkomt dat ruwe content-bestanden via het web opgevraagd worden.
*
* @since 2.6.4
* @since 2.6.5
*/
// Block direct access to content files
if (strpos($path, '/content/') === 0) {
@@ -153,7 +153,7 @@ if (strpos($path, '/content/') === 0) {
* slaan de controles over. Het requestStatus wordt bijgehouden voor
* latere logging en blocking.
*
* @since 2.6.4
* @since 2.6.5
*/
// Load RequestLogger for IP & request logging
require_once __DIR__ . '/../cms/core/class/RequestLogger.php';
@@ -208,7 +208,7 @@ if (!$isAllowedIp) {
/**
* CMS-instantie aanmaken met de geladen configuratie.
*
* @since 2.6.4
* @since 2.6.5
*/
// Instantiate CMS instance
$cms = new CodePressCMS($config);
@@ -219,7 +219,7 @@ $cms = new CodePressCMS($config);
* Land, IP-anonimisatie en analytics-instellingen worden bepaald op basis
* van de analytics-configuratie.
*
* @since 2.6.4
* @since 2.6.5
*/
// Analytics & GeoIP settings
$analyticsSettings = $config['analytics'] ?? [];
@@ -232,7 +232,7 @@ if (!empty($analyticsSettings['enabled'])) {
/**
* IP-anonimisatie toepassen voor opslag indien ingeschakeld.
*
* @since 2.6.4
* @since 2.6.5
*/
// Apply IP anonymization for storage if enabled
$storedIp = !empty($analyticsSettings['anonymize_ip'])
@@ -246,7 +246,7 @@ $storedIp = !empty($analyticsSettings['anonymize_ip'])
* een request-logregel, vuurt een LogManager-requestevent en registreert
* geaggregeerde analytics (mits ingeschakeld en IP niet uitgesloten).
*
* @since 2.6.4
* @since 2.6.5
*/
// Log page view (not for media/assets)
if (!str_starts_with($path, '/-media/') && !str_starts_with($path, '/-assets/')) {
@@ -291,7 +291,7 @@ if (!str_starts_with($path, '/-media/') && !str_starts_with($path, '/-assets/'))
*
* Geeft 429 bij rate-limit en 403 bij andere blokkades, met noindex-headers.
*
* @since 2.6.4
* @since 2.6.5
*/
// Block request if status is not ok
if ($requestStatus !== 'ok') {
@@ -309,6 +309,6 @@ if ($requestStatus !== 'ok') {
/**
* Pagina renderen via de CodePressCMS-instantie.
*
* @since 2.6.4
* @since 2.6.5
*/
$cms->render();
+2 -2
View File
@@ -7,7 +7,7 @@
* repository en contact). Wordt door de rest van het CMS gebruikt om de
* versie te tonen en vereisten te valideren.
*
* @since 2.6.4
* @since 2.6.5
* @package CodePress
*/
/**
@@ -15,7 +15,7 @@
*/
return [
'version' => '2.6.4',
'version' => '2.6.5',
'release_date' => '2026-08-26',
'codename' => 'Lyra',
'status' => 'stable',