Quelltext des aktuellen Standes
<?php
declare(strict_types=1);
/**
* Absicherung des Material-Design-2-Themes (zweite Frontend-Design-Option).
*
* Das Theme wird nur bei aktivem Instanz-Schalter geladen und darf das
* Standard-Design in keinem Fall beeinflussen. Deshalb muss jede Regel auf
* body.design-material gescoped sein; außerdem müssen Schalter, Layout-
* Einbindung und Laufzeit-Übernahme zusammenpassen.
*/
return static function (): void {
$root = dirname(__DIR__);
$theme = file_get_contents($root . '/public/assets/css/theme-material.css');
test('Theme-Datei existiert und ist nicht leer', function () use ($theme) {
assertTrue(is_string($theme) && strlen($theme) > 1000);
});
test('Jede Regel ist auf body.design-material gescoped', function () use ($theme) {
$css = preg_replace('#/\*.*?\*/#s', '', $theme);
foreach (preg_split('/}/', $css) as $block) {
$selPart = trim(preg_replace('/\{.*/s', '', $block));
if ($selPart === '') {
continue;
}
foreach (explode(',', $selPart) as $sel) {
$sel = trim($sel);
if ($sel === '') {
continue;
}
assertTrue(
str_starts_with($sel, 'body.design-material'),
'Nicht gescopter Selektor: ' . $sel
);
}
}
});
test('Theme setzt keine Styles ausserhalb des Schalters (kein :root)', function () use ($theme) {
assertFalse(str_contains($theme, ':root'));
});
test('Alle Web-Layouts ausser Admin binden Theme nur bei design_style=material ein', function () use ($root) {
foreach (['main', 'auth', 'portal', 'status_public', 'signature'] as $name) {
$layout = file_get_contents($root . '/templates/layouts/' . $name . '.php');
assertTrue(str_contains($layout, 'theme-material.css'), $name . ': Theme-Link fehlt');
assertTrue(str_contains($layout, "design_style ?? 'standard') === 'material'"), $name . ': Schalter fehlt');
assertTrue(str_contains($layout, 'design-material'), $name . ': Body-Klasse fehlt');
}
assertFalse(str_contains(file_get_contents($root . '/templates/layouts/admin.php'), 'theme-material'));
});
test('Eigenstaendige oeffentliche Seiten binden das Theme ein', function () use ($root) {
$pages = [
'templates/public/form.php', 'templates/public/result.php', 'templates/public/status.php',
'templates/approval/show.php', 'templates/approval/result.php',
'templates/feedback/invalid.php', 'templates/feedback/rate.php', 'templates/feedback/thanks.php',
'templates/vault/share_view.php',
];
foreach ($pages as $p) {
$tpl = file_get_contents($root . '/' . $p);
assertTrue(str_contains($tpl, 'theme-material.css'), $p . ': Theme-Link fehlt');
assertTrue(str_contains($tpl, 'design-material'), $p . ': Body-Klasse fehlt');
}
});
test('Laufzeit-Override und Render-Daten kennen design_style', function () use ($root) {
// Geprüft wird die Deckung, nicht die Schreibweise: Der Schlüssel darf
// einzeln oder über die gesammelten Listen übernommen werden.
$index = file_get_contents($root . '/public/index.php');
$uebernommen = str_contains($index, "runtimeConfig['app']['design_style']");
if (!$uebernommen && preg_match_all('/\$backendApp(?:Strings|Flags)\s*=\s*\[(.*?)\];/s', $index, $listen)) {
$uebernommen = str_contains(implode('', $listen[1]), "'design_style'");
}
assertTrue($uebernommen, 'design_style wird nicht aus runtime.php übernommen');
$base = file_get_contents($root . '/src/Controllers/BaseController.php');
assertTrue(str_contains($base, "\$data['design_style']"));
$app = file_get_contents($root . '/src/Core/Application.php');
assertTrue(str_contains($app, "\$data['design_style']"));
});
test('Admin-Einstellungen speichern design_style als standard/material', function () use ($root) {
$ctrl = file_get_contents($root . '/src/Controllers/Admin/SettingsController.php');
assertTrue(str_contains($ctrl, "use_material_design') ? 'material' : 'standard'"));
$tpl = file_get_contents($root . '/templates/admin/settings/index.php');
assertTrue(str_contains($tpl, 'use_material_design'));
});
};