v2.6.7 (Lyra): Essential plugins consistent tonen + docblock-vereiste

Vervolg op v2.6.6: vier plekken lazen nog ruwe enabled_plugins zonder
essential-forcering. handleDashboard(), handleContentFiles/Edit() en
AdminPluginAPI::getEnabledPlugins() forceren nu essential plugins
consistent met PluginManager. Dode functie countEnabledPlugins()
verwijderd. AGENTS.md aangevuld met verplichte docblock-sectie.
This commit is contained in:
2026-08-27 20:13:20 +00:00
parent f7e8837a1c
commit d039114f21
5 changed files with 139 additions and 21 deletions
+8
View File
@@ -37,6 +37,14 @@
- [ ] AGENTS.md + config.json.example bijwerken
- [ ] Verificatie: php -l, curl met Host-header, domein-switch in admin testen
## v2.6.7 (2026-08-27) ✅
- [x] Bug: dashboard toonde essential plugins (Dashboard, Navigation) als inactief — handleDashboard() admin.php:670 las ruwe config zonder essential-forcering; gefixt met isProtectedPlugin()
- [x] Bug: AdminPluginAPI::getEnabledPlugins() retourneerde ruwe config.enabled_plugins zonder essential-forcering — bevraagt nu PluginManager (single source of truth); fallback doet zelf essential-scan
- [x] Bug: content-editor plugin-selector (handleContentFiles/handleContentEdit) miste Navigation als die uit enabled_plugins raakte — essential/protected content-plugins worden nu altijd getoond (isProtectedPlugin())
- [x] Opschonen: dode functie countEnabledPlugins() verwijderd (nergens aangeroepen)
- [x] Docs: AGENTS.md aangevuld met verplichte docblock-sectie (WordPress-stijl, @since, @param, @return, {@type}-structuur)
- [x] Verslag gemaakt (docs/release-notes/v2.6.7.md)
## v2.6.6 (2026-08-27) ✅
- [x] Bug: essential/protected plugins (Dashboard, Navigation) konden niet meer geactiveerd worden als ze uit enabled_plugins raakten — core forceert nu laden van essential plugins (plugin.json `essential: true`); admin-UI toont ze altijd als Actief; toggle-handler staat aanzetten wél toe, uitzetten blijft geblokkeerd; isProtectedPlugin() dekt nu ook essential (alle delete/bewerk/file-handlers automatisch beschermd)
- [x] Docs: guide plugin-development (NL/EN) beschrijving `essential`-veld bijgewerkt ("altijd geladen" + niet uit te schakelen/bewerken/verwijderen)
+33 -1
View File
@@ -141,13 +141,45 @@ class AdminPluginAPI implements PluginAPIInterface
/**
* Haal de lijst met ingeschakelde plugins op.
*
* Essential plugins (plugin.json `essential: true`) worden altijd
* geretourneerd, ook als ze niet in config.enabled_plugins staan, en
* komen consistent met de PluginManager op de eerste positie. Als de
* PluginManager is geïnjecteerd wordt dien geautoriseerde lijst
* gebruikt (single source of truth); anders valt de methode terug op
* config.enabled_plugins aangevuld met een lokale essential-scan.
*
* @since 2.6.5
*
* @return array<int,string> Lijst met ingeschakelde plugin-namen.
*/
public function getEnabledPlugins(): array
{
return $this->config['enabled_plugins'] ?? [];
if ($this->pluginManager !== null) {
return $this->pluginManager->getEnabledPlugins();
}
$enabled = $this->config['enabled_plugins'] ?? [];
if (!is_array($enabled)) {
$enabled = [];
}
// Fallback: essential plugins forceren als de PluginManager niet
// geïnjecteerd is (houdt de lijst consistent met loadPlugins()).
$pluginsDir = $this->projectRoot . '/plugins';
if (is_dir($pluginsDir)) {
foreach (glob($pluginsDir . '/*', GLOB_ONLYDIR) as $pluginDir) {
$pluginName = basename($pluginDir);
$pluginJsonFile = $pluginDir . '/plugin.json';
if (!file_exists($pluginJsonFile)) {
continue;
}
$data = json_decode(file_get_contents($pluginJsonFile), true);
if (is_array($data) && ($data['essential'] ?? false) === true
&& !in_array($pluginName, $enabled, true)
) {
$enabled[] = $pluginName;
}
}
}
return array_values($enabled);
}
/**
+88
View File
@@ -0,0 +1,88 @@
# v2.6.7 (Lyra) — Essential plugins consistent tonen + docblock-vereiste
Releasedatum: 2026-08-27
Codename: Lyra
Status: stable
## Samenvatting
Vervolg op v2.6.6 (essential plugins altijd laden). In v2.6.6 forcerde
alleen `PluginManager::loadPlugins()` het laden van essential plugins —
maar vier andere plekken in de code lazen nog de ruwe
`config.enabled_plugins` zonder essential-forcering, waardoor
essential/protected plugins (Dashboard, Navigation) op diverse plekken
als "Inactief" of onzichtbaar toonden, ondanks dat ze effectief draaiden.
Deze release maakt alle plekken die plugin-status bepalen consistent met
`PluginManager`. Daarnaast is de docblock-vereiste formeel vastgelegd in
`AGENTS.md`.
## Wijzigingen
### `cms/core/plugin/AdminPluginAPI.php`
- `getEnabledPlugins()` bevraagt nu de geïnjecteerde PluginManager (single
source of truth) wanneer aanwezig. Fallback (zonder PluginManager) doet
zelf een essential-scan over de plugins-directory, consistent met
`PluginManager::loadPlugins()`. Essential plugins worden altijd
geretourneerd, ook als ze niet in `config.enabled_plugins` staan.
### `public/admin.php`
- `handleDashboard()` (plugin-overzicht op `/admin/dashboard`): `enabled`
wordt `true` voor protected/essential plugins via `isProtectedPlugin()`.
Eerder toonde het dashboard essential plugins als inactief als ze uit
`enabled_plugins` raakten.
- `handleContentFiles()` en `handleContentEdit()` (content-editor
plugin-multiselect): essential/protected content-plugins worden altijd
getoond in de selector (via `isProtectedPlugin()`). Eerder ontbrak
`Navigation` uit de keuzelijst als die niet in `enabled_plugins` stond,
terwijl hij effectief draaide.
- Dode functie `countEnabledPlugins()` verwijderd (nergens aangeroepen).
### `AGENTS.md`
- Nieuwe sectie `Docblocks (verplicht)`: elke plugin, theme, class, method
en function (ook private/protected) krijgt een WordPress-stijl docblock.
Bevat het vereiste formaat met `@since`, `@param`, `@return` en de
`{ @type }` array-structuur. Controle bij elke verandering.
## Consistentie-check (alle 17 plekken)
Alle plekken die plugin-status bepalen zijn gecontroleerd. Na v2.6.7 leest
geen enkele plek meer de ruwe `enabled_plugins` zonder essential-forcering:
| Plek | Voor v2.6.7 | Na v2.6.7 |
|------|-------------|-----------|
| `PluginManager::loadPlugins()` | ✅ v2.6.6 | ✅ |
| `PluginManager::isEnabled()` | ✅ | ✅ |
| `CodePressCMS` (front-end) | ✅ (via PM) | ✅ |
| `handleDashboard()` admin.php:670 | ❌ ruw | ✅ geforceerd |
| `handleContentFiles()` admin.php:1272 | ❌ ruw | ✅ geforceerd |
| `handleContentEdit()` admin.php:1973 | ❌ ruw | ✅ geforceerd |
| `handlePlugins()` admin.php:3827 | ✅ v2.6.6 | ✅ |
| `handlePluginsToggle()` admin.php:5252 | ✅ v2.6.6 | ✅ |
| `AdminPluginAPI::getEnabledPlugins()` | ❌ ruw | ✅ via PM |
| `Dashboard.php` (plugin) | via API | ✅ via gefixte API |
| guide-sidebar (admin.php:5650) | ✅ direct require | ✅ |
| `config.php` default | ✅ bevat Navigation | ✅ |
| `countEnabledPlugins()` | dode code | verwijderd |
## Tests uitgevoerd
- `php -l` over alle PHP-bestanden (zonder vendor): 0 syntax-errors.
- Functionele tests (`cli/test/functional/run-tests.sh` tegen Apache):
16/16 PASS (100%).
- Pentest (`cli/test/pentest/pentest.sh`): 29/29 SAFE, 0 vulnerabilities.
- Accessibility / WCAG 2.1 AA (`cli/test/accessibility.sh`): 25/25 PASS.
- Runtime-check `AdminPluginAPI::getEnabledPlugins()` met lege
`enabled_plugins`: retourneert `Dashboard`+`Navigation` (zowel via PM
als via fallback).
- Runtime-check `handleDashboard()` simulatie met lege
`enabled_plugins`: `Dashboard`+`Navigation` tonen `enabled=true`.
- Runtime-check content-editor selector met lege `enabled_plugins`:
`Navigation` zichtbaar (essential content-plugin).
## Upgrade-instructies
1. Pull de nieuwe versie.
2. Geen verdere actie nodig — alle plekken tonen essential plugins nu
consistent als actief, ongeacht de staat van `enabled_plugins` in
`config.json`.
+9 -19
View File
@@ -666,13 +666,15 @@ function handleDashboard($auth, $config, $twig, $user, $csrf, $siteConfig): void
];
// Build plugin overview (name => enabled status)
// Essential/protected plugins worden altijd als actief getoond,
// ongeacht enabled_plugins (consistent met PluginManager::loadPlugins()).
$pluginOverview = [];
$enabledPlugins = $siteConfig['enabled_plugins'] ?? [];
if (is_dir($pluginsDir)) {
foreach (glob($pluginsDir . '/*', GLOB_ONLYDIR) as $pluginDir) {
$pluginName = basename($pluginDir);
$pluginOverview[$pluginName] = [
'enabled' => in_array($pluginName, $enabledPlugins, true),
'enabled' => in_array($pluginName, $enabledPlugins, true) || isProtectedPlugin($pluginName),
];
}
}
@@ -1264,10 +1266,12 @@ function handleContentFiles($auth, $config, $twig, $user, $csrf, $siteConfig): v
$contentPlugins = getContentPlugins($pluginsDir);
// Keep only enabled plugins so the selector reflects what actually runs.
// enabled_plugins lives in config.json ($siteConfig), not in app.php.
// Essential/protected plugins worden altijd getoond (consistent met
// PluginManager::loadPlugins() en handlePlugins()).
$enabledPlugins = $siteConfig['enabled_plugins'] ?? [];
$availablePlugins = [];
foreach ($contentPlugins as $p) {
if (in_array($p['name'], $enabledPlugins, true)) {
if (in_array($p['name'], $enabledPlugins, true) || isProtectedPlugin($p['name'])) {
$availablePlugins[] = $p;
}
}
@@ -1963,12 +1967,14 @@ function handleContentEdit($auth, $config, $twig, $user, $csrf, $siteConfig): vo
// Get available content plugins (only enabled content-type plugins).
// enabled_plugins lives in config.json ($siteConfig), not in app.php.
// Essential/protected plugins worden altijd getoond (consistent met
// PluginManager::loadPlugins() en handlePlugins()).
$pluginsDir = $config['plugins_dir'];
$contentPlugins = getContentPlugins($pluginsDir);
$enabledPlugins = $siteConfig['enabled_plugins'] ?? [];
$availablePlugins = [];
foreach ($contentPlugins as $p) {
if (in_array($p['name'], $enabledPlugins, true)) {
if (in_array($p['name'], $enabledPlugins, true) || isProtectedPlugin($p['name'])) {
$availablePlugins[] = $p;
}
}
@@ -5938,22 +5944,6 @@ function countDirs(string $dir): int
return $count;
}
/**
* Telt het aantal ingeschakelde plugins in de site-config.
*
* @since 2.6.5
*
* @param string $pluginsDir Plugins-directory (ongebruikt, voor compatibiliteit).
* @param string $configJson Pad naar config.json.
* @return int Aantal ingeschakelde plugins.
*/
function countEnabledPlugins(string $pluginsDir, string $configJson): int
{
$config = file_exists($configJson) ? json_decode(file_get_contents($configJson), true) : [];
$enabled = $config['enabled_plugins'] ?? [];
return count($enabled);
}
/**
* Berekent recursief de totale bestandsgrootte (in bytes) van een directory.
*
+1 -1
View File
@@ -15,7 +15,7 @@
*/
return [
'version' => '2.6.6',
'version' => '2.6.7',
'release_date' => '2026-08-27',
'codename' => 'Lyra',
'status' => 'stable',