, * aktuell: array{id: int, name: string}|null, * gesamt: int, * meldungen: list} $zustand */ private function __construct(private array $zustand) { } /** * Eine neue Warteschlange über die übergebenen Bankverbindungen – in der * Reihenfolge, in der sie auch in der Übersicht stehen. * * @param list> $zugaenge */ public static function fuer(array $zugaenge): self { $offen = []; foreach ($zugaenge as $zugang) { $offen[] = ['id' => (int)$zugang['id'], 'name' => (string)$zugang['name']]; } return new self([ 'offen' => $offen, 'aktuell' => null, 'gesamt' => count($offen), 'meldungen' => [], ]); } /** * Die Warteschlange aus einem gespeicherten Zustand – `null`, wenn keiner * (mehr) da ist. */ public static function aus(mixed $zustand): ?self { if (!is_array($zustand) || !is_array($zustand['offen'] ?? null)) { return null; } return new self([ 'offen' => array_values($zustand['offen']), 'aktuell' => is_array($zustand['aktuell'] ?? null) ? $zustand['aktuell'] : null, 'gesamt' => (int)($zustand['gesamt'] ?? 0), 'meldungen' => is_array($zustand['meldungen'] ?? null) ? $zustand['meldungen'] : [], ]); } /** @return array Der Zustand zum Ablegen in der Sitzung. */ public function zustand(): array { return $this->zustand; } /** * Die nächste Bankverbindung – `null`, wenn alle durch sind. Sie gilt ab * jetzt als die laufende, bis ihr Ergebnis vermerkt ist. * * @return array{id: int, name: string}|null */ public function naechste(): ?array { $this->zustand['aktuell'] = array_shift($this->zustand['offen']); return $this->zustand['aktuell']; } /** @return array{id: int, name: string}|null Die gerade laufende Bankverbindung. */ public function aktuell(): ?array { return $this->zustand['aktuell']; } /** * Das Ergebnis der laufenden Bankverbindung festhalten. * * @param array $ergebnis wie von `FinTsAbruf`/`PaypalAbruf` */ public function vermerke(array $ergebnis): void { if ($this->zustand['aktuell'] === null) { return; } $fehler = ($ergebnis['status'] ?? 'fehler') === 'fehler'; $this->notiere( $fehler ? 'fehler' : 'erfolg', ($fehler ? 'Abruf fehlgeschlagen: ' : '') . (string)($ergebnis['meldung'] ?? '') ); } /** Die laufende Bankverbindung ohne Ergebnis hinter sich lassen. */ public function ueberspringe(): void { if ($this->zustand['aktuell'] !== null) { $this->notiere('fehler', 'Übersprungen, die Freigabe wurde abgebrochen.'); } } /** * Den ganzen Lauf abbrechen: Die laufende und alle noch offenen * Bankverbindungen werden nicht mehr abgerufen. */ public function abbrechen(): void { $offen = count($this->zustand['offen']) + ($this->zustand['aktuell'] !== null ? 1 : 0); $this->zustand['aktuell'] = null; $this->zustand['offen'] = []; if ($offen > 0) { $this->zustand['meldungen'][] = [ 'typ' => 'fehler', 'meldung' => sprintf( 'Abruf abgebrochen – %d Bankverbindung%s nicht abgerufen.', $offen, $offen === 1 ? '' : 'en' ), ]; } } /** * Wo der Lauf steht – für die TAN-Maske, damit dort klar ist, welche Bank * gerade fragt und wie viele noch folgen. * * @return array{nummer: int, gesamt: int, name: string} */ public function stand(): array { return [ 'nummer' => $this->zustand['gesamt'] - count($this->zustand['offen']), 'gesamt' => $this->zustand['gesamt'], 'name' => (string)($this->zustand['aktuell']['name'] ?? ''), ]; } /** @return list Je Bankverbindung eine Meldung. */ public function meldungen(): array { return $this->zustand['meldungen']; } private function notiere(string $typ, string $meldung): void { $this->zustand['meldungen'][] = [ 'typ' => $typ, 'meldung' => $this->zustand['aktuell']['name'] . ': ' . $meldung, ]; $this->zustand['aktuell'] = null; } }