'Testfirma', 'strasse' => 'Teststr. 1', 'plz' => '12345', 'ort' => 'Testort', ]); } finally { restore_error_handler(); } $this->assert( $warnings === [], 'Setting::update() ohne optionale Keys erzeugt keine Warnings (erhalten: ' . implode(' | ', $warnings) . ')' ); $stored = Setting::get(); $this->assertEquals('Rechnung %RNR%', $stored['mail_subject_template'], 'Fehlender Betreff fällt auf den Default zurück'); $this->assertEquals('Testfirma', $stored['firma'], 'Firma wurde gespeichert'); // 2) Logo liegt in data/logo, die DB speichert nur den Dateinamen. // Bewusst ein eigener Testdateiname – deleteLogo() löscht die Datei // physisch, ein echtes logo.png darf davon nie getroffen werden. $testFile = 'logo-test-' . getmypid() . '.png'; $testPath = Config::get('logo_dir') . '/' . $testFile; Setting::setLogo($testFile); $this->assertEquals($testFile, Setting::get()['logo_path'], 'setLogo() speichert nur den Dateinamen'); $abs = Setting::logoAbsolutePath(); $this->assertEquals($testPath, $abs, 'logoAbsolutePath() zeigt in das Logo-Datenverzeichnis'); $this->assert( !str_contains((string)$abs, '/public/'), 'Logo liegt außerhalb des Web-Roots' ); // Altbestände mit webroot-relativem Präfix bleiben auffindbar, falls // Migration 089 noch nicht gelaufen ist Setting::setLogo('static/uploads/logo/' . $testFile); $this->assertEquals( $testPath, Setting::logoAbsolutePath(), 'Legacy-Pfad wird auf das Logo-Verzeichnis abgebildet' ); // deleteLogo() entfernt Datei und DB-Eintrag if (!is_dir((string)Config::get('logo_dir'))) { mkdir((string)Config::get('logo_dir'), 0755, true); } file_put_contents($testPath, 'dummy'); Setting::setLogo($testFile); Setting::deleteLogo(); $this->assert(!file_exists($testPath), 'deleteLogo() entfernt die Datei aus data/logo'); $this->assert(empty(Setting::get()['logo_path']), 'deleteLogo() entfernt den Pfad'); $this->assert(Setting::logoAbsolutePath() === null, 'Ohne Logo liefert logoAbsolutePath() null'); // 3) Belege und Logo liegen getrennt und beide außerhalb von public/ $uploadDir = (string)Config::get('upload_dir'); $logoDir = (string)Config::get('logo_dir'); $this->assert(!str_contains($uploadDir, '/public/'), 'Belegverzeichnis liegt außerhalb des Web-Roots'); $this->assert($uploadDir !== $logoDir, 'Belege und Logo haben getrennte Verzeichnisse'); $this->assert(str_ends_with($uploadDir, '/data/belege'), 'Belege liegen in data/belege'); $this->assert(str_ends_with($logoDir, '/data/logo'), 'Logo liegt in data/logo'); // 3) Das Logo-Upload-Formular darf nicht in #settings-form verschachtelt sein – // sonst verwirft der Browser das innere