Updater-System (OpenNIT-Modell) im isolierten updater/-Ordner

Zieht Quellcode + DB-Migrationen über einen HTTP-Update-Proxy nach.
Vollständig isoliert: eigener Namespace Updater\, eigener Autoloader,
eigene Settings (updater/storage/updater-settings.json), eigenes
Migrations-System (_updater_migrations), eigener AuditLogger.

Komponenten (alle in updater/):
- UpdateManager: Version/.version, Maintenance, Progress, checkForUpdates,
  installUpdate (Staging + PROTECTED_PATHS + Migrationen + opcache + finally)
- MigrationRunner: MySQL-Tracking, string-/kommentar-bewusster SQL-Splitter,
  isIgnorableSqlError, 60s-Lockfile-Cache
- UpdateController + admin/update.php (dünner Entry-Shim), Inline-Admin-UI
  mit Channel-Selector, Update-Check, Progress-Bar, Migrations-Tab
- UpdaterFactory (zentraler Channel-Fallback), AuditLogger (audit_log)
- Templates: maintenance.html, update.php; routes.php (Doku)
- README.md mit vollständiger Rückbau-Anleitung

Einzige Bestandscode-Änderung: 4-Zeilen-Maintenance-Hook in index.php
(markiert mit "// Updater maintenance hook").

Proxy: update.loheide.eu/openvouchertool[-development]
This commit is contained in:
Claude 2026-06-05 18:51:51 +00:00
parent 3483da274f
commit 43149074c9
No known key found for this signature in database
14 changed files with 1374 additions and 0 deletions

View file

@ -0,0 +1,51 @@
<?php
namespace Updater;
/**
* Zentrale Fabrik fuer den UpdateManager.
*
* Der Channel wird ausschliesslich aus einer EIGENEN, isolierten Settings-Datei
* gelesen (updater/storage/updater-settings.json) NICHT aus der bestehenden
* Settings-/Config-Konvention des Projekts. Beim Rueckbau einfach loeschbar.
*
* Default-Channel-Fallback existiert NUR hier (eine Stelle).
*/
final class UpdaterFactory
{
private static function settingsFile(): string
{
return __DIR__ . '/storage/updater-settings.json';
}
public static function create(\Database $db, ?AuditLogger $audit = null): UpdateManager
{
$settings = self::loadSettings();
$channel = $settings['channel'] ?? 'stable';
return new UpdateManager($db, $audit, $channel);
}
public static function loadSettings(): array
{
$file = self::settingsFile();
if (!is_file($file)) {
return [];
}
$data = json_decode((string)file_get_contents($file), true);
return is_array($data) ? $data : [];
}
public static function saveChannel(string $channel): void
{
if (!isset(UpdateManager::CHANNELS[$channel])) {
$channel = 'stable';
}
$settings = self::loadSettings();
$settings['channel'] = $channel;
$dir = dirname(self::settingsFile());
if (!is_dir($dir)) {
@mkdir($dir, 0775, true);
}
file_put_contents(self::settingsFile(), json_encode($settings, JSON_PRETTY_PRINT));
}
}