Anzeigename → absoluter Pfad */ public static function verzeichnisse(): array { $wurzel = dirname(__DIR__, 2); $import = trim((string)Einstellung::get('import_qif_verzeichnis', 'data/import'), '/'); return [ $import => $wurzel . '/' . $import, 'data/tmp' => $wurzel . '/data/tmp', ]; } /** Verzeichnis für Arbeitsdateien; wird bei Bedarf angelegt. */ public static function tempVerzeichnis(): string { $pfad = dirname(__DIR__, 2) . '/data/tmp'; if (!is_dir($pfad)) { mkdir($pfad, 0o775, true); } return $pfad; } /** Lief das Aufräumen heute schon? */ public static function faellig(?string $heute = null): bool { if (self::tage() === 0) { return false; } $heute = $heute ?? date('Y-m-d'); $letzter = (string)Einstellung::get(self::EINSTELLUNG_LAUF, ''); return substr($letzter, 0, 10) !== $heute; } /** * Beiläufiger Lauf: höchstens einmal am Tag, und ohne dass ein Fehler die * aufrufende Seite mitreißt – wer den Import öffnet, will importieren, nicht * eine Fehlermeldung übers Aufräumen lesen. * * @return array|null Das Ergebnis, oder null wenn nichts anstand. */ public static function beiGelegenheit(): ?array { if (!self::faellig()) { return null; } try { return self::ausfuehren(); } catch (\Throwable $e) { DebugLog::schreibe('housekeeping', 'Aufräumen fehlgeschlagen: ' . $e->getMessage()); return null; } } /** * @return array{tage: int, geprueft: int, geloescht: int, bytes: int, * dateien: list, trockenlauf: bool} */ public static function ausfuehren(bool $trockenlauf = false): array { $tage = self::tage(); $grenze = time() - $tage * 86400; $ergebnis = [ 'tage' => $tage, 'geprueft' => 0, 'geloescht' => 0, 'bytes' => 0, 'dateien' => [], 'trockenlauf' => $trockenlauf, ]; if ($tage === 0) { return $ergebnis; } foreach (self::verzeichnisse() as $name => $pfad) { $echt = realpath($pfad); if ($echt === false || !is_dir($echt)) { continue; } foreach (scandir($echt) ?: [] as $eintrag) { if ($eintrag === '.' || $eintrag === '..') { continue; } $datei = $echt . '/' . $eintrag; // Nur gewöhnliche Dateien direkt im Verzeichnis: ein Symlink // zeigte womöglich aus dem überwachten Bereich heraus, und ein // Unterverzeichnis hat hier niemand angelegt. if (is_link($datei) || !is_file($datei)) { continue; } $ergebnis['geprueft']++; $alter = filemtime($datei); if ($alter === false || $alter > $grenze) { continue; } $groesse = (int)filesize($datei); if (!$trockenlauf && !@unlink($datei)) { continue; } $ergebnis['geloescht']++; $ergebnis['bytes'] += $groesse; $ergebnis['dateien'][] = $name . '/' . $eintrag; } } if (!$trockenlauf) { Einstellung::set(self::EINSTELLUNG_LAUF, date('Y-m-d H:i:s'), 'import'); } return $ergebnis; } }