$failedMsg) flash('error', $failedSlug . ': ' . $failedMsg);
redirect('/staff/plugins.php');
}
if ($action === 'catalog_install' && plugin_valid_slug($slug)) {
$res = plugin_catalog_install($pdo, $slug);
if ($res['ok']) {
audit_log($staff['id'], ($res['updated'] ? 'Plugin aus dem Katalog aktualisiert: ' : 'Plugin aus dem Katalog installiert: ') . "{$res['slug']} {$res['version']} (SHA-256 {$res['hash']}" . ($res['signed'] ? ', signiert' : ', nicht signiert') . ')');
flash('success', plugin_install_message($res, plugins_installed($pdo)[$res['slug']] ?? []));
redirect('/staff/plugins.php');
}
$errors[] = $res['error'];
}
if (in_array($action, ['activate', 'deactivate'], true) && plugin_valid_slug($slug)) {
if ($action === 'activate') {
$bk = create_backup(); // vor Datenbank-Änderungen des Plugins
if (!$bk['ok']) $errors[] = 'Backup fehlgeschlagen – das Plugin wurde nicht aktiviert: ' . ($bk['error'] ?? 'unbekannter Fehler');
}
if (!$errors) {
$manifest = plugin_read_manifest(plugins_dir() . '/' . $slug)[0];
// Signierte Plugins aus dem Katalog des Herausgebers brauchen keine zusätzliche Bestätigung; manuell hochgeladene schon
$row = plugins_installed($pdo)[$slug] ?? [];
$fromCatalog = ($row['source'] ?? '') === 'catalog' && !empty($row['signature_ok']);
$approve = (!empty($_POST['confirm_permissions']) || $fromCatalog) && $manifest ? $manifest['permissions'] : null;
$res = plugin_set_active($pdo, $slug, $action === 'activate', $approve);
if ($res['ok']) {
audit_log($staff['id'], ($action === 'activate' ? 'Plugin aktiviert: ' : 'Plugin deaktiviert: ') . $slug);
flash('success', $action === 'activate' ? 'Plugin aktiviert.' : 'Plugin deaktiviert.');
redirect('/staff/plugins.php');
}
$errors[] = $res['error'];
}
}
if ($action === 'uninstall' && plugin_valid_slug($slug)) {
$res = plugin_uninstall($pdo, $slug, !empty($_POST['remove_data']));
if ($res['ok']) {
audit_log($staff['id'], 'Plugin entfernt: ' . $slug . (!empty($_POST['remove_data']) ? ' (inkl. Daten)' : ''));
flash('success', 'Plugin entfernt.');
redirect('/staff/plugins.php');
}
$errors[] = $res['error'];
}
}
$installed = plugins_installed($pdo);
$manifests = [];
foreach ($installed as $slug => $row) $manifests[$slug] = plugin_read_manifest(plugins_dir() . '/' . $slug)[0];
$disabled = plugins_globally_disabled();
$strict = plugin_strict_mode();
$official = plugin_official_configured();
$catalog = plugin_catalog_url() !== '' ? plugin_catalog_cached(isset($_GET['refresh']), 60) : null;
// Katalogeinträge je Plugin (für die Vorschaubilder der installierten Plugins)
$catBySlug = [];
if ($catalog && !empty($catalog['ok'])) foreach ($catalog['plugins'] as $__c) $catBySlug[$__c['slug']] = $__c;
$hasKey = plugin_publisher_key() !== '';
$catalogHost = (string) (parse_url(plugin_catalog_url(), PHP_URL_HOST) ?: '');
$updates = plugin_updates_available($pdo);
$updBySlug = [];
foreach ($updates as $u) $updBySlug[$u['slug']] = $u;
// Zustand je Plugin: active | inactive | error; dazu Update-Kennzeichen
$stateOf = [];
$counts = ['all' => 0, 'active' => 0, 'inactive' => 0, 'error' => 0, 'update' => 0];
foreach ($installed as $slug => $p) {
$bad = !$manifests[$slug] || (!$p['is_active'] && (int) $p['fail_count'] >= PLUGIN_FAIL_LIMIT);
$st = $bad ? 'error' : ($p['is_active'] ? 'active' : 'inactive');
$stateOf[$slug] = $st;
$counts['all']++;
$counts[$st]++;
if (isset($updBySlug[$slug])) $counts['update']++;
}
// Erste Menüseite eines geladenen Plugins für den Link „Öffnen“
$openUrl = [];
foreach (plugin_state()['menus'] as $__m) {
if (!isset($openUrl[$__m['plugin']])) $openUrl[$__m['plugin']] = '/staff/plugin.php?p=' . rawurlencode($__m['plugin']) . '&page=' . rawurlencode($__m['page']);
}
$tab = in_array($_GET['tab'] ?? '', ['add', 'settings'], true) ? $_GET['tab'] : 'installed';
if ($errors) {
$failedAction = $_POST['action'] ?? '';
if (in_array($failedAction, ['install', 'catalog_install'], true)) $tab = 'add';
if ($failedAction === 'save_settings') $tab = 'settings';
}
$banner = function (array $c, string $name): string {
$inner = !empty($c['preview'])
? ''
: '' . e(mb_strtoupper(mb_substr($name, 0, 1))) . '';
return '
plugins/.disabled oder Einstellung plugins.enabled = false). Bereits aktive Plugins werden nicht geladen.= $m && $m['description'] !== '' ? e($m['description']) : (!$m ? 'plugin.json fehlt oder ist ungültig – das Plugin kann nicht geladen werden.' : '') ?>
Von = $m && $m['author'] !== '' ? e($m['author']) : 'unbekannt' ?>
= $m && $m['description'] !== '' ? nl2br(e($m['description'])) : '' ?>
plugin.json fehlt oder ist ungültig – das Plugin kann nicht geladen werden.
Dieses Plugin fordert keine Berechtigungen an.
Es ist noch keine Katalog-Adresse hinterlegt. Trage unter „Katalog & Schlüssel“ die Adresse der Plugin-Webseite ein, dann könnt ihr Plugins direkt von dort installieren.
= e($c['description']) ?>
Von = $c['author'] !== '' ? e($c['author']) : 'unbekannt' ?>
= nl2br(e($c['description'])) ?>
Dieses Plugin fordert keine Berechtigungen an.
Hier könnt ihr eigene Plugins als ZIP installieren oder aktualisieren, auch ohne Signatur. Diese Plugins sind nicht vom Herausgeber geprüft und laufen mit allen Rechten des Systems, auch mit Zugriff auf die gesamte Datenbank. Installiert nur Code, den ihr selbst geschrieben oder geprüft habt.
Das Plugin wird nach der Installation nicht automatisch aktiviert. Vor dem Aktivieren bestätigt ihr die Berechtigungen, die es anfordert.